diff --git a/.gitignore b/.gitignore index 51dec909..43763d0e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ build/ data/ .kotlin/ +jcef-bundle/ + !gradle-wrapper.jar /kotlin-js-store/yarn.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fa6c42d..5c7c3d6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,11 @@ ## Unreleased ### Added +- Moved plotly-kt repo inside this one ### Changed +- Kotlin 2.0 +- DataForge 0.9 ### Deprecated diff --git a/build.gradle.kts b/build.gradle.kts index 24159d9f..4f519d6a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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-2" + version = "0.5.0-dev-1" } subprojects { diff --git a/demo/compose-desktop-demo/build.gradle.kts b/demo/compose-desktop-demo/build.gradle.kts index ff6bc292..e3616074 100644 --- a/demo/compose-desktop-demo/build.gradle.kts +++ b/demo/compose-desktop-demo/build.gradle.kts @@ -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 { diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index 48a3298e..84fa067c 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -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" diff --git a/demo/js-playground/build.gradle.kts b/demo/js-playground/build.gradle.kts index 86067e7a..fe0e4115 100644 --- a/demo/js-playground/build.gradle.kts +++ b/demo/js-playground/build.gradle.kts @@ -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 { diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts index 82263640..75bf7069 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -1,6 +1,7 @@ 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 } diff --git a/demo/playground/build.gradle.kts b/demo/playground/build.gradle.kts index 7d5dd0b0..2019da01 100644 --- a/demo/playground/build.gradle.kts +++ b/demo/playground/build.gradle.kts @@ -43,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) } diff --git a/docs/tutorials/tutorial-event-display.md b/docs/tutorials/tutorial-event-display.md index e257178d..595890ca 100644 --- a/docs/tutorials/tutorial-event-display.md +++ b/docs/tutorials/tutorial-event-display.md @@ -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") diff --git a/gradle.properties b/gradle.properties index c4510ba9..057e8f4c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,4 +4,4 @@ kotlin.mpp.stability.nowarn=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx4G -toolsVersion=0.15.2-kotlin-2.0.0-RC1 +toolsVersion=0.15.4-kotlin-2.0.0 diff --git a/plotly/CHANGELOG.md b/plotly/CHANGELOG.md new file mode 100644 index 00000000..4b24f56b --- /dev/null +++ b/plotly/CHANGELOG.md @@ -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 diff --git a/plotly/README.md b/plotly/README.md new file mode 100644 index 00000000..9467f7c3 --- /dev/null +++ b/plotly/README.md @@ -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. + diff --git a/plotly/build.gradle.kts b/plotly/build.gradle.kts new file mode 100644 index 00000000..0825ced9 --- /dev/null +++ b/plotly/build.gradle.kts @@ -0,0 +1,8 @@ +allprojects { + group = "space.kscience" + version = "0.7.2" +} + +readme { + readmeTemplate = file("docs/templates/README-TEMPLATE.md") +} \ No newline at end of file diff --git a/plotly/docs/Dependency structure.vsdx b/plotly/docs/Dependency structure.vsdx new file mode 100644 index 00000000..a54b3c53 Binary files /dev/null and b/plotly/docs/Dependency structure.vsdx differ diff --git a/plotly/docs/logo.png b/plotly/docs/logo.png new file mode 100644 index 00000000..45739391 Binary files /dev/null and b/plotly/docs/logo.png differ diff --git a/plotly/docs/logo.svg b/plotly/docs/logo.svg new file mode 100644 index 00000000..81063c4b --- /dev/null +++ b/plotly/docs/logo.svg @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plotly/docs/logo_text.svg b/plotly/docs/logo_text.svg new file mode 100644 index 00000000..242fc981 --- /dev/null +++ b/plotly/docs/logo_text.svg @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + Plotly.kt + + + + + + + + + + + + + + diff --git a/plotly/docs/models.uml b/plotly/docs/models.uml new file mode 100644 index 00000000..0dc050f7 --- /dev/null +++ b/plotly/docs/models.uml @@ -0,0 +1,259 @@ + + + JAVA + kscience.plotly.models + + kscience.plotly.models.Contours + kscience.plotly.models.ShapeType + kscience.plotly.models.TextPosition + kscience.plotly.models.MeasureMode + kscience.plotly.models.BoxMode + kscience.plotly.models.Ticks + kscience.plotly.models.Cumulative + kscience.plotly.models.LegendOrientation + kscience.plotly.models.ViolinPoints + kscience.plotly.models.Margin + kscience.plotly.models.SelectMarker + kscience.plotly.models.VerticalAlign + kscience.plotly.models.ShapeSizeMode + kscience.plotly.models.BoxMean + kscience.plotly.models.Title + kscience.plotly.models.Line + kscience.plotly.models.Heatmap + kscience.plotly.models.SelectPoints + kscience.plotly.models.AxisType + kscience.plotly.models.HeatmapContour + kscience.plotly.models.GroupNorm + kscience.plotly.models.Trace + kscience.plotly.models.FillType + kscience.plotly.models.StackGaps + kscience.plotly.models.ShapeLayer + kscience.plotly.models.Legend + kscience.plotly.models.BoxHoveron + kscience.plotly.models.Shape + kscience.plotly.models.ShapeFillRule + kscience.plotly.models.TickMode + kscience.plotly.models.YAnchor + kscience.plotly.models.Bar + kscience.plotly.models.ContourSpec + kscience.plotly.models.GradientType + kscience.plotly.models.ScatterGL + kscience.plotly.models.HistogramDirection + kscience.plotly.models.Contour + kscience.plotly.models.PieDirection + kscience.plotly.models.Color + kscience.plotly.models.ContoursType + kscience.plotly.models.CurrentBin + kscience.plotly.models.Layout + kscience.plotly.models.TraceValues + kscience.plotly.models.Scatter + kscience.plotly.models.LayoutLine + kscience.plotly.models.ScatterHoveron + kscience.plotly.models.SelectedPoints + kscience.plotly.models.ErrorType + kscience.plotly.models.HoverMode + kscience.plotly.models.ViolinSide + kscience.plotly.models.ColorBar + kscience.plotly.models.BarNorm + kscience.plotly.models.Domain + kscience.plotly.models.Box + kscience.plotly.models.MarkerLine + kscience.plotly.models.ConstrainText + kscience.plotly.models.Histogram2DContour + kscience.plotly.models.ViolinBox + kscience.plotly.models.TraceOrder + kscience.plotly.models.Histogram2D + kscience.plotly.models.Orientation + kscience.plotly.models.Axis + kscience.plotly.models.TraceKt + kscience.plotly.models.Error + kscience.plotly.models.ZsmoothType + kscience.plotly.models.XAnchor + kscience.plotly.models.Marker + kscience.plotly.models.Dash + kscience.plotly.models.BarMode + kscience.plotly.models.Violin + kscience.plotly.models.ViolinScaleMode + kscience.plotly.models.TraceType + kscience.plotly.models.ContoursColoring + kscience.plotly.models.Symbol + kscience.plotly.models.Calendar + kscience.plotly.models.Pie + kscience.plotly.models.BoxPoints + kscience.plotly.models.Ref + kscience.plotly.models.ViolinMode + kscience.plotly.models.Visible + kscience.plotly.models.Gradient + kscience.plotly.models.MeanLine + kscience.plotly.models.Text + kscience.plotly.models.HeatmapGL + kscience.plotly.models.Table2D + kscience.plotly.models.Histogram + kscience.plotly.models.SizeMode + kscience.plotly.models.QuartileMethod + kscience.plotly.models.LineShape + kscience.plotly.models.HorizontalAlign + kscience.plotly.models.Font + kscience.plotly.models.HistFunc + kscience.plotly.models.ScatterMode + kscience.plotly.models.Bins + kscience.plotly.models.ViolinHoveron + kscience.plotly.models.HistNorm + kscience.plotly.models.TextInfo + kscience.plotly.models.DataType + kscience.plotly.models.SpanMode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Properties + + All + private + + diff --git a/plotly/docs/overview.html b/plotly/docs/overview.html new file mode 100644 index 00000000..2d5dcbfd --- /dev/null +++ b/plotly/docs/overview.html @@ -0,0 +1,467 @@ + + + + + + Made with Remarkable! + + + + + + + +

+ Plotly.kt: v0.2.0 +

+
+

+ logo +

+

+ Intro +

+

+ Data visualization tasks are closely related to educational, scientific and business issues. There is a great number of graphic libraries, usually written and available from languages, designed for data science issues. But few of them could be used from Kotlin, that prevents many people from using it for statistical computing and graphics. One of the most popular browser graphic libraries is + + Plotly + + available from most languages (JavaScript itslef, Python, R, etc). That’s why it was decided to create Kotlin wrapper for Plotly, which uses JVM backend for drawing in browser some static HTML-page or starting its own web-server. The original Plotly API was preserved as much as possible and some new features and abilites were added. +
+ New Plotly.kt logo symbolizes the relationship between the Kotlin language and initial Plotly library. Therefore, gradient colors and the shape of the letter “K” have been taken from Kotlin + + logo + + , while white histogram and cerulean dots are borrowed from Plotly + + logo + + to illustrate that a greate variety of types of fully styled plots can be created with + + Plotly.kt + + ! +

+

+ Plotly.kt content +

+

+ Our version of Plotly.kt library contains different classes for each supported type of plot, such as Histogram, Heatmap or Pie Chart, inherited from Trace, which is the main class containing all nonspecific methods and parameters. It was made in this way to flatten library model structure and to avoid duplication of large chunks of code, which is one of the problems of Plotly library itself, in which it is nearly impossible even to download all the + + documentation + + . Each class contains an + + init + + block where the trace type is set: +

+
class Pie : Trace() {
+    init {
+        type = TraceType.pie
+    }
+}
+
+

+ At present Plotly.kt supports all major trace types which could be combined in one plot: +

+
enum class TraceType {
+    bar,
+    box,
+    contour,
+    heatmap,
+    heatmapgl,
+    histogram,
+    histogram2d,
+    histogram2dcontour,
+    pie,
+    scatter,
+    scattergl,
+    violin
+}
+
+

+ Many other trace types will be supported in the future, such as 3D graphics, polar plots and geo maps. Calling one of the not supported types will cause an error. +

+

+ All traces subclasses (Bar, Box, etc), Trace itself and additional layout and trace classes (Font, Title, Line, etc) contain a big number of different methods and parameters, and all of them are, in fact, delegates: +

+
class Domain : Scheme() {
+    /**
+     * Sets the horizontal domain of this pie trace (in plot fraction).
+     * Default: [0, 1]
+     */
+    var x by numberList()
+
+    /**
+     * Sets the vertical domain of this pie trace (in plot fraction).
+     * Default: [0, 1]
+     */
+    var y by numberList()
+}
+
+

+ These classes are inherited from + + Scheme + + , which allows to store the values of all parameters as a dynamic tree. It is important for a dynamic update of the plot, therefore now real-time updates are available. +
+ Moreover, if you need one of the unsupported methods, you can change the trace configuration, which is similarly available owing to the dynamic tree structure: +

+
val trace = Trace.invoke(x, y) {
+    name = "sin"
+    /** The hover text definition is currently not supported.
+     *  We are applying it directly to configuration.
+     *  It is still observable in the same way as other properties but is not type safe.
+     */
+    configure {
+        set("text", x.map { "label for  $it" })
+    }
+}
+
+

+ Plot description is divided into two parts as in the original Plotly library: +
+ - + + traces + + : data values, type of the plot, common parameters and specific parameters (e.g. bins width and color for Bar chart), text +
+ - + + layout + + : frame settings including axes, annotations, legend and shapes +

+

+ Unfortunately, sometimes it’s not easy to make out what type the object is (a trace or a layout) and it is the next problem of the original Plotly API. If you have any problems with that, please check Plotly + + documentation + +
+ But let’s start with creating a simple scatter plot: +

+
Plotly.plot {
+    scatter {
+        x(1, 2, 3, 4)
+        y(12, 5, 2, 12)
+        mode = ScatterMode.`lines+markers`
+    }
+    layout {
+        title = "Line and Scatter Plot"
+    }
+}.makeFile()
+
+

+ Features +

+

+ This version of Plotly.kt library contains several modules, which are necessary for supporting some important features: +
+ 1. + + Static page + + is an isolated whole HTML page, which can contain custom headers, separators and any other Kotlin-html elements. Plot description is built in the created page in JSON format. After calling + + plot.makeFile() + + function corresponding HTML file saves to a temporary file, which can be customized. +
+ For example, support of LaTeX rendering with + + MathJax + + can be added by using custom headers. But you need to remember that some font properties have no effect while using LaTeX, that is why you need to change font size or width by means of LaTeX itself: +

+
Plotly.page(mathJaxHeader) {
+    plot {
+        scatter { 
+            x.set(xValues)
+            y.set(yValues)
+            name = "\$\\Large{y = \\mathrm{sin}\\,x}\$"  // increasing fontsize
+        }
+    }
+}.makeFile()
+
+

+ The resulting graph looks as follows. +

+
+
+ +

+ Full tutorial of drawing the sinus picture is available + + here + + , while the source code can be found + + here + +
+ 2. + + HtmlFragment + + is a fragment of Kotlin-html page, which also can be displayed in the browser after calling + + .makefile() + + . +
+ For example, if you need to download plot in SVG format instead of PNG, you can directly change configuration of the plot and change Plotly browser button from “download png” to “download svg”: +

+
Plotly.fragment {
+    val plotConfig = PlotlyConfig {
+        saveAsSvg()
+    }
+    plot(config = plotConfig) {...}
+}.makeFile()
+
+
+

+ After applying this configuration the result will be as follows. +

+
+
+ +

+ Example code is available + + here + +
+ 3. + + Static plot + + is created after inserting resulting JSON with the plot description into a template HTML page. If you don’t need any specific settings using static plots is the easiest way to get an image. +

+
+
+ +

+ Full source code is available + + here + +
+ 4. + + Dynamic plot + + collects updates in the Collector, which flushes updates once in a while (50 ms by default). After flushing takes place only modified parts of the plot are updated. +
+ 5. + + Jupyter + + is now supported in an experimental mode. There are two modules in Plotly.kt repository for Kotlin-Jupyter: static (call + + %use plotly + + ) and server (call + + %use plotly-server + + ). The server is needed to make dynamic charts with real-time updates. For the time being integration with JupyterLab works stably, but there are some problems with Jupyter Classic because of the properties, connected with files and scripts loading. +

+
%use plotly
+import kotlin.math.*
+
+Plotly.plot {
+    scatter {
+        x.set((0..100).map { it.toDouble() / 100.0 })
+        y.set((0..100).map { sin(2.0 * PI * (it.toDouble() / 100.0)) })
+    }
+
+    layout {
+        title = "$\\text{TeX is Number} \\displaystyle\\sum_{n=1}^\\infty \\frac{-e^{i\\pi}}{2^n}!$"
+    }
+}
+
+

+ static +

+

+ MathJax is loaded automatically, so LaTeX rendering works without any custom headers. More examples with Jupyter notebooks, + + plotly.json + + and + + plotly-server.json + + are available + + here + +

+

+ Examples +

+

+ A plot object contains flexible + + traces + + and + + layout + + sections and you need to specify at least one of them to make an image. Don’t forget to call + + makeFile() + + ! +

+
val plot = Plotly.plot {
+    scatter {
+        x(1, 2, 3, 4, 5)
+        y("a", "b", "c", "d")
+    }
+    layout {
+        title = "Graph name"
+    }
+}
+plot.makeFile()
+
+

+ There is a great number of customizable parameters and methods. +
+ Let’s have a look at some cases: +

+ +
layout {
+    xaxis {
+        type = AxisType.log
+        autorange = true
+    }
+    yaxis {
+        type = AxisType.log
+        autorange = true
+    }
+}
+
+
+
+ + +
plot {
+    heatmap {
+        colorscale = Value.of(listOf(listOf(0, "#B1D1FC"), listOf(1, "#7E1E9C"))
+    }
+}
+
+
+
+ + +
plot {
+    bar {
+        orientation = Orientation.h
+    }
+}
+
+
+
+ +

+ Vertical axes labels show some + + css named + + colors. +

+

+ For more examples please check our + + GitHub + + page. Thank you for your attention! +

+ + + + + + diff --git a/plotly/docs/templates/ARTIFACT-TEMPLATE.md b/plotly/docs/templates/ARTIFACT-TEMPLATE.md new file mode 100644 index 00000000..6b921b05 --- /dev/null +++ b/plotly/docs/templates/ARTIFACT-TEMPLATE.md @@ -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}") +> } +> ``` \ No newline at end of file diff --git a/plotly/docs/templates/README-TEMPLATE.md b/plotly/docs/templates/README-TEMPLATE.md new file mode 100644 index 00000000..9467f7c3 --- /dev/null +++ b/plotly/docs/templates/README-TEMPLATE.md @@ -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. + diff --git a/plotly/docs/tutorials/HowToDrawASinus.md b/plotly/docs/tutorials/HowToDrawASinus.md new file mode 100644 index 00000000..d8a26f01 --- /dev/null +++ b/plotly/docs/tutorials/HowToDrawASinus.md @@ -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() // 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 \ No newline at end of file diff --git a/plotly/docs/tutorials/jupyter.md b/plotly/docs/tutorials/jupyter.md new file mode 100644 index 00000000..1b969ac8 --- /dev/null +++ b/plotly/docs/tutorials/jupyter.md @@ -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 +
+ +
+``` + +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. \ No newline at end of file diff --git a/plotly/examples/README.md b/plotly/examples/README.md new file mode 100644 index 00000000..d4e1c528 --- /dev/null +++ b/plotly/examples/README.md @@ -0,0 +1,4 @@ +# Module examples + + + diff --git a/plotly/examples/build.gradle.kts b/plotly/examples/build.gradle.kts new file mode 100644 index 00000000..2fa4f1b7 --- /dev/null +++ b/plotly/examples/build.gradle.kts @@ -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" +//} \ No newline at end of file diff --git a/plotly/examples/compose-demo/README.md b/plotly/examples/compose-demo/README.md new file mode 100644 index 00000000..4a110357 --- /dev/null +++ b/plotly/examples/compose-demo/README.md @@ -0,0 +1,4 @@ +# Module compose-demo + + + diff --git a/plotly/examples/compose-demo/api/compose-demo.api b/plotly/examples/compose-demo/api/compose-demo.api new file mode 100644 index 00000000..5f14e789 --- /dev/null +++ b/plotly/examples/compose-demo/api/compose-demo.api @@ -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 ()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; +} + diff --git a/plotly/examples/compose-demo/build.gradle.kts b/plotly/examples/compose-demo/build.gradle.kts new file mode 100644 index 00000000..fe3133a9 --- /dev/null +++ b/plotly/examples/compose-demo/build.gradle.kts @@ -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 { + kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" +} + +compose { + desktop { + application { + mainClass = "space.kscience.plotly.compose.AppKt" + } + } +} diff --git a/plotly/examples/compose-demo/src/jvmMain/kotlin/space/kscience/plotly/compose/App.kt b/plotly/examples/compose-demo/src/jvmMain/kotlin/space/kscience/plotly/compose/App.kt new file mode 100644 index 00000000..ed307250 --- /dev/null +++ b/plotly/examples/compose-demo/src/jvmMain/kotlin/space/kscience/plotly/compose/App.kt @@ -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() + } + } +} diff --git a/plotly/examples/compose-demo/src/jvmMain/kotlin/space/kscience/plotly/compose/server.kt b/plotly/examples/compose-demo/src/jvmMain/kotlin/space/kscience/plotly/compose/server.kt new file mode 100644 index 00000000..5965eb6f --- /dev/null +++ b/plotly/examples/compose-demo/src/jvmMain/kotlin/space/kscience/plotly/compose/server.kt @@ -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): 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) +} + + diff --git a/plotly/examples/fx-demo/README.md b/plotly/examples/fx-demo/README.md new file mode 100644 index 00000000..a9cd9946 --- /dev/null +++ b/plotly/examples/fx-demo/README.md @@ -0,0 +1,4 @@ +# Module fx-demo + + + diff --git a/plotly/examples/fx-demo/build.gradle.kts b/plotly/examples/fx-demo/build.gradle.kts new file mode 100644 index 00000000..f316d883 --- /dev/null +++ b/plotly/examples/fx-demo/build.gradle.kts @@ -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 { + kotlinOptions.freeCompilerArgs = kotlinOptions.freeCompilerArgs +"-Xopt-in=kotlin.RequiresOptIn" +} diff --git a/plotly/examples/fx-demo/src/main/kotlin/space/kscience/plotly/fx/PlotlyFXApp.kt b/plotly/examples/fx-demo/src/main/kotlin/space/kscience/plotly/fx/PlotlyFXApp.kt new file mode 100644 index 00000000..7af14394 --- /dev/null +++ b/plotly/examples/fx-demo/src/main/kotlin/space/kscience/plotly/fx/PlotlyFXApp.kt @@ -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) { + launch(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() + } +} \ No newline at end of file diff --git a/plotly/examples/fx-demo/src/main/kotlin/space/kscience/plotly/fx/PlotlyFXController.kt b/plotly/examples/fx-demo/src/main/kotlin/space/kscience/plotly/fx/PlotlyFXController.kt new file mode 100644 index 00000000..c0dc21be --- /dev/null +++ b/plotly/examples/fx-demo/src/main/kotlin/space/kscience/plotly/fx/PlotlyFXController.kt @@ -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") + } + } +} \ No newline at end of file diff --git a/plotly/examples/fx-demo/src/main/kotlin/space/kscience/plotly/fx/server.kt b/plotly/examples/fx-demo/src/main/kotlin/space/kscience/plotly/fx/server.kt new file mode 100644 index 00000000..cf5e021a --- /dev/null +++ b/plotly/examples/fx-demo/src/main/kotlin/space/kscience/plotly/fx/server.kt @@ -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) +} + + diff --git a/plotly/examples/js-demo/README.md b/plotly/examples/js-demo/README.md new file mode 100644 index 00000000..b99b85d5 --- /dev/null +++ b/plotly/examples/js-demo/README.md @@ -0,0 +1,4 @@ +# Module js-demo + + + diff --git a/plotly/examples/js-demo/build.gradle.kts b/plotly/examples/js-demo/build.gradle.kts new file mode 100644 index 00000000..11bf896c --- /dev/null +++ b/plotly/examples/js-demo/build.gradle.kts @@ -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 { + kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" +} \ No newline at end of file diff --git a/plotly/examples/js-demo/src/main/kotlin/space/kscience/plotly/jsdemo/main.kt b/plotly/examples/js-demo/src/main/kotlin/space/kscience/plotly/jsdemo/main.kt new file mode 100644 index 00000000..abb6c5ee --- /dev/null +++ b/plotly/examples/js-demo/src/main/kotlin/space/kscience/plotly/jsdemo/main.kt @@ -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.() -> 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()) + } + } +} + + diff --git a/plotly/examples/js-demo/src/main/resources/index.html b/plotly/examples/js-demo/src/main/resources/index.html new file mode 100644 index 00000000..57e567ed --- /dev/null +++ b/plotly/examples/js-demo/src/main/resources/index.html @@ -0,0 +1,11 @@ + + + + + Plotly.kt js demo + + + +
+ + \ No newline at end of file diff --git a/plotly/examples/native-demo/README.md b/plotly/examples/native-demo/README.md new file mode 100644 index 00000000..79582d8a --- /dev/null +++ b/plotly/examples/native-demo/README.md @@ -0,0 +1,4 @@ +# Module native-demo + + + diff --git a/plotly/examples/native-demo/build.gradle.kts b/plotly/examples/native-demo/build.gradle.kts new file mode 100644 index 00000000..bb03b243 --- /dev/null +++ b/plotly/examples/native-demo/build.gradle.kts @@ -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 { + kotlinOptions.freeCompilerArgs = kotlinOptions.freeCompilerArgs +"-Xopt-in=kotlin.RequiresOptIn" +} diff --git a/plotly/examples/native-demo/src/mingwX64Main/kotlin/plotlyMain.kt b/plotly/examples/native-demo/src/mingwX64Main/kotlin/plotlyMain.kt new file mode 100644 index 00000000..968d4966 --- /dev/null +++ b/plotly/examples/native-demo/src/mingwX64Main/kotlin/plotlyMain.kt @@ -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") +} \ No newline at end of file diff --git a/plotly/examples/notebooks/.ipynb_checkpoints/Issue-sim-checkpoint.ipynb b/plotly/examples/notebooks/.ipynb_checkpoints/Issue-sim-checkpoint.ipynb new file mode 100644 index 00000000..5738cc7a --- /dev/null +++ b/plotly/examples/notebooks/.ipynb_checkpoints/Issue-sim-checkpoint.ipynb @@ -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\n", + "}\n", + "\n", + "interface Strategy{\n", + " fun selectIssue(day: Int, issues: List): Issue?\n", + "}\n", + "\n", + "class WorkResult(val issues: List, 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{\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{\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?{\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?{\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?{\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 +} diff --git a/plotly/examples/notebooks/.ipynb_checkpoints/latex-demo-checkpoint.ipynb b/plotly/examples/notebooks/.ipynb_checkpoints/latex-demo-checkpoint.ipynb new file mode 100644 index 00000000..99d88de5 --- /dev/null +++ b/plotly/examples/notebooks/.ipynb_checkpoints/latex-demo-checkpoint.ipynb @@ -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": [ + "
\n", + "\n", + "\n", + "\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": [ + "
\n", + "
\n", + " \n", + " \n", + "
\n", + "
\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 +} diff --git a/plotly/examples/notebooks/.ipynb_checkpoints/plotly-experimental-checkpoint.json b/plotly/examples/notebooks/.ipynb_checkpoints/plotly-experimental-checkpoint.json new file mode 100644 index 00000000..0f57bffd --- /dev/null +++ b/plotly/examples/notebooks/.ipynb_checkpoints/plotly-experimental-checkpoint.json @@ -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)" + } +} \ No newline at end of file diff --git a/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo-checkpoint.ipynb b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo-checkpoint.ipynb new file mode 100644 index 00000000..6183fe94 --- /dev/null +++ b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo-checkpoint.ipynb @@ -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 +} diff --git a/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo-classic-checkpoint.ipynb b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo-classic-checkpoint.ipynb new file mode 100644 index 00000000..3b7d34d9 --- /dev/null +++ b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo-classic-checkpoint.ipynb @@ -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": [ + "\n", + " \n", + " \n", + " Plotly.kt\n", + " \n", + " \n", + " \n", + "
\n", + " \n", + "
\n", + "
\n", + "

A custom separator

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + " \n", + "\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": [ + "\n", + " \n", + " \n", + " Plotly.kt\n", + " \n", + " \n", + " \n", + "
\n", + " \n", + "
\n", + " \n", + "\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 +} diff --git a/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo-experimental-checkpoint.ipynb b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo-experimental-checkpoint.ipynb new file mode 100644 index 00000000..c1fe910a --- /dev/null +++ b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo-experimental-checkpoint.ipynb @@ -0,0 +1,313 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2021-01-14T18:47+0300", + "start_time": "2021-01-14T18:47+0300" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + " " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%use @file[plotly-experimental.json]\n", + "import kotlin.math.*" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2021-01-14T18:47+0300", + "start_time": "2021-01-14T18:47+0300" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "

A custom separator

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n" + ] + }, + "execution_count": 2, + "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 { renderer ->\n", + " plot(\"above\", 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": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2021-01-14T18:47+0300", + "start_time": "2021-01-14T18:47+0300" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + " \n", + "
\n", + "
\n" + ] + }, + "execution_count": 3, + "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": 6, + "metadata": { + "ExecuteTime": { + "end_time": "2021-01-14T18:48+0300", + "start_time": "2021-01-14T18:48+0300" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "HTML(\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2021-01-14T18:47+0300", + "start_time": "2021-01-14T18:47+0300" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + " \n", + "
\n", + "
\n" + ] + }, + "execution_count": 5, + "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": 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.0-dev-1206" + }, + "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 +} diff --git a/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo_1-checkpoint.ipynb b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo_1-checkpoint.ipynb new file mode 100644 index 00000000..ac0f6dd5 --- /dev/null +++ b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-demo_1-checkpoint.ipynb @@ -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": [ + "
The server is already running on 8882. It must be shut down first to be restarted.
\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": [ + "
\n", + "
\n", + " \n", + " \n", + "
\n", + "
\n", + "

A custom separator

\n", + "
\n", + "
\n", + "
\n", + " \n", + " \n", + "
\n", + "
\n", + "
\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": [ + "
\n", + "
\n", + " \n", + " \n", + "
\n", + "
\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": [ + "
\n", + "
\n", + " \n", + " \n", + "
\n", + "
\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": [ + "
Update server is stopped
\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 +} diff --git a/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-server-demo-checkpoint.ipynb b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-server-demo-checkpoint.ipynb new file mode 100644 index 00000000..6a7d9823 --- /dev/null +++ b/plotly/examples/notebooks/.ipynb_checkpoints/plotlykt-server-demo-checkpoint.ipynb @@ -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 +} diff --git a/plotly/examples/notebooks/Issue-sim.ipynb b/plotly/examples/notebooks/Issue-sim.ipynb new file mode 100644 index 00000000..5738cc7a --- /dev/null +++ b/plotly/examples/notebooks/Issue-sim.ipynb @@ -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\n", + "}\n", + "\n", + "interface Strategy{\n", + " fun selectIssue(day: Int, issues: List): Issue?\n", + "}\n", + "\n", + "class WorkResult(val issues: List, 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{\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{\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?{\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?{\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?{\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 +} diff --git a/plotly/examples/notebooks/latex-demo.ipynb b/plotly/examples/notebooks/latex-demo.ipynb new file mode 100644 index 00000000..99d88de5 --- /dev/null +++ b/plotly/examples/notebooks/latex-demo.ipynb @@ -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": [ + "
\n", + "\n", + "\n", + "\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": [ + "
\n", + "
\n", + " \n", + " \n", + "
\n", + "
\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 +} diff --git a/plotly/examples/notebooks/plotlykt-demo.ipynb b/plotly/examples/notebooks/plotlykt-demo.ipynb new file mode 100644 index 00000000..13581ef5 --- /dev/null +++ b/plotly/examples/notebooks/plotlykt-demo.ipynb @@ -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", + "
\n", + " debug\n", + "
\n", + " \"\"\".trimIndent()\n", + ")" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "HTML(\"\"\"\n", + "\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", + "\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 +} diff --git a/plotly/examples/notebooks/plotlykt-server-demo.ipynb b/plotly/examples/notebooks/plotlykt-server-demo.ipynb new file mode 100644 index 00000000..59b7d210 --- /dev/null +++ b/plotly/examples/notebooks/plotlykt-server-demo.ipynb @@ -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 +} diff --git a/plotly/examples/src/main/kotlin/annotation/plotWithAnnotation.kt b/plotly/examples/src/main/kotlin/annotation/plotWithAnnotation.kt new file mode 100644 index 00000000..c0a03361 --- /dev/null +++ b/plotly/examples/src/main/kotlin/annotation/plotWithAnnotation.kt @@ -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() +} diff --git a/plotly/examples/src/main/kotlin/bar/BarChartWithHoverText.kt b/plotly/examples/src/main/kotlin/bar/BarChartWithHoverText.kt new file mode 100644 index 00000000..40587cad --- /dev/null +++ b/plotly/examples/src/main/kotlin/bar/BarChartWithHoverText.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/bar/ColoredAndStyledBarChart.kt b/plotly/examples/src/main/kotlin/bar/ColoredAndStyledBarChart.kt new file mode 100644 index 00000000..4b95c890 --- /dev/null +++ b/plotly/examples/src/main/kotlin/bar/ColoredAndStyledBarChart.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/bar/GroupedBarChart.kt b/plotly/examples/src/main/kotlin/bar/GroupedBarChart.kt new file mode 100644 index 00000000..e803b208 --- /dev/null +++ b/plotly/examples/src/main/kotlin/bar/GroupedBarChart.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/bar/GroupedBarDirectLabels.kt b/plotly/examples/src/main/kotlin/bar/GroupedBarDirectLabels.kt new file mode 100644 index 00000000..8b703309 --- /dev/null +++ b/plotly/examples/src/main/kotlin/bar/GroupedBarDirectLabels.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/bar/HorizontalBarPlot.kt b/plotly/examples/src/main/kotlin/bar/HorizontalBarPlot.kt new file mode 100644 index 00000000..5309c613 --- /dev/null +++ b/plotly/examples/src/main/kotlin/bar/HorizontalBarPlot.kt @@ -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() + 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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/bar/IndividualBarBase.kt b/plotly/examples/src/main/kotlin/bar/IndividualBarBase.kt new file mode 100644 index 00000000..2de07598 --- /dev/null +++ b/plotly/examples/src/main/kotlin/bar/IndividualBarBase.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/bar/IndividualBarColorsAndWidth.kt b/plotly/examples/src/main/kotlin/bar/IndividualBarColorsAndWidth.kt new file mode 100644 index 00000000..d38786d5 --- /dev/null +++ b/plotly/examples/src/main/kotlin/bar/IndividualBarColorsAndWidth.kt @@ -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(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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/bar/StackedBarChart.kt b/plotly/examples/src/main/kotlin/bar/StackedBarChart.kt new file mode 100644 index 00000000..dcca6f59 --- /dev/null +++ b/plotly/examples/src/main/kotlin/bar/StackedBarChart.kt @@ -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(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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/box/BasicBoxPlot.kt b/plotly/examples/src/main/kotlin/box/BasicBoxPlot.kt new file mode 100644 index 00000000..b9d5aa21 --- /dev/null +++ b/plotly/examples/src/main/kotlin/box/BasicBoxPlot.kt @@ -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() + val y1 = mutableListOf() + + 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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/box/FullyStyledBoxPlot.kt b/plotly/examples/src/main/kotlin/box/FullyStyledBoxPlot.kt new file mode 100644 index 00000000..2da1dc6a --- /dev/null +++ b/plotly/examples/src/main/kotlin/box/FullyStyledBoxPlot.kt @@ -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 { + val value = mutableListOf() + 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
Anthony", "Dwyane
Wade", "Deron
Williams", + "Brook
Lopez", "Damian
Lillard", "David
West", + "Blake
Griffin", "David
Lee", "Demar
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() + 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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/box/HorizontalBoxPlot.kt b/plotly/examples/src/main/kotlin/box/HorizontalBoxPlot.kt new file mode 100644 index 00000000..1ea2b085 --- /dev/null +++ b/plotly/examples/src/main/kotlin/box/HorizontalBoxPlot.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/box/StylingMeanAndSd.kt b/plotly/examples/src/main/kotlin/box/StylingMeanAndSd.kt new file mode 100644 index 00000000..ea618315 --- /dev/null +++ b/plotly/examples/src/main/kotlin/box/StylingMeanAndSd.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/box/StylingOutliers.kt b/plotly/examples/src/main/kotlin/box/StylingOutliers.kt new file mode 100644 index 00000000..71d66414 --- /dev/null +++ b/plotly/examples/src/main/kotlin/box/StylingOutliers.kt @@ -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(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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/candlestick/basicCandleStick.kt b/plotly/examples/src/main/kotlin/candlestick/basicCandleStick.kt new file mode 100644 index 00000000..4ed9413a --- /dev/null +++ b/plotly/examples/src/main/kotlin/candlestick/basicCandleStick.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/candlestick/dynamicCandleStick.kt b/plotly/examples/src/main/kotlin/candlestick/dynamicCandleStick.kt new file mode 100644 index 00000000..78a51880 --- /dev/null +++ b/plotly/examples/src/main/kotlin/candlestick/dynamicCandleStick.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/complexDynamicServer.kt b/plotly/examples/src/main/kotlin/complexDynamicServer.kt new file mode 100644 index 00000000..132a9626 --- /dev/null +++ b/plotly/examples/src/main/kotlin/complexDynamicServer.kt @@ -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 Flow.windowed(size: Int): Flow> { + val queue = ConcurrentLinkedQueue() + return flow { + this@windowed.collect { + queue.add(it) + if (queue.size >= size) { + queue.poll() + } + emit(queue) + } + } +} + +suspend fun Trace.updateFrom(axisName: String, flow: Flow>) { + flow.collect { + axis(axisName).numbers = it + } +} + +suspend fun Trace.updateXYFrom(flow: Flow>>) { + 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> = 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> = 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>> = 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) +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/contour/BasicContour.kt b/plotly/examples/src/main/kotlin/contour/BasicContour.kt new file mode 100644 index 00000000..ded6ef10 --- /dev/null +++ b/plotly/examples/src/main/kotlin/contour/BasicContour.kt @@ -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> = listOf( + listOf(10, 10.625, 12.5, 15.625, 20.0), + listOf(5.625, 6.25, 8.125, 11.25, 15.625), + listOf(2.5, 3.125, 5.0, 8.125, 12.5), + listOf(0.625, 1.25, 3.125, 6.25, 10.625), + listOf(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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/contour/ColoredContourPlot.kt b/plotly/examples/src/main/kotlin/contour/ColoredContourPlot.kt new file mode 100644 index 00000000..0e4e0fd7 --- /dev/null +++ b/plotly/examples/src/main/kotlin/contour/ColoredContourPlot.kt @@ -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>() + + 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() +} diff --git a/plotly/examples/src/main/kotlin/contour/ConnectNullGaps.kt b/plotly/examples/src/main/kotlin/contour/ConnectNullGaps.kt new file mode 100644 index 00000000..feb8e39e --- /dev/null +++ b/plotly/examples/src/main/kotlin/contour/ConnectNullGaps.kt @@ -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(null, null, null, 12, 13, 14, 15, 16), + listOf(null, 1, null, 11, null, null, null, 17), + listOf(null, 2, 6, 7, null, null, null, 18), + listOf(null, 3, null, 8, null, null, null, 19), + listOf(5, 4, 10, 9, null, null, null, 20), + listOf(null, null, null, 27, null, null, null, 21), + listOf(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() +} diff --git a/plotly/examples/src/main/kotlin/contour/ContourLinesLabels.kt b/plotly/examples/src/main/kotlin/contour/ContourLinesLabels.kt new file mode 100644 index 00000000..f86f6fbd --- /dev/null +++ b/plotly/examples/src/main/kotlin/contour/ContourLinesLabels.kt @@ -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>() + + 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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/contour/CustomazingSpaceBetweenTicks.kt b/plotly/examples/src/main/kotlin/contour/CustomazingSpaceBetweenTicks.kt new file mode 100644 index 00000000..4daaee13 --- /dev/null +++ b/plotly/examples/src/main/kotlin/contour/CustomazingSpaceBetweenTicks.kt @@ -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(10, 10.625, 12.5, 15.625, 20), + listOf(5.625, 6.25, 8.125, 11.25, 15.625), + listOf(2.5, 3.125, 5.0, 8.125, 12.5), + listOf(0.625, 1.25, 3.125, 6.25, 10.625), + listOf(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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/contour/NegativeDashContourLines.kt b/plotly/examples/src/main/kotlin/contour/NegativeDashContourLines.kt new file mode 100644 index 00000000..5394ce12 --- /dev/null +++ b/plotly/examples/src/main/kotlin/contour/NegativeDashContourLines.kt @@ -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>() + val z2 = mutableListOf>() + + 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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/contour/SimpleContourPlot.kt b/plotly/examples/src/main/kotlin/contour/SimpleContourPlot.kt new file mode 100644 index 00000000..56a16a81 --- /dev/null +++ b/plotly/examples/src/main/kotlin/contour/SimpleContourPlot.kt @@ -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() + val y1 = mutableListOf() + val z1 = mutableListOf>() + + 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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/customPage.kt b/plotly/examples/src/main/kotlin/customPage.kt new file mode 100644 index 00000000..26ff5a50 --- /dev/null +++ b/plotly/examples/src/main/kotlin/customPage.kt @@ -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() +} diff --git a/plotly/examples/src/main/kotlin/downloadChartAsSVG.kt b/plotly/examples/src/main/kotlin/downloadChartAsSVG.kt new file mode 100644 index 00000000..bcd76d73 --- /dev/null +++ b/plotly/examples/src/main/kotlin/downloadChartAsSVG.kt @@ -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
size: 40", "B
size: 60", "C
size: 80", "D
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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/dynamicServer.kt b/plotly/examples/src/main/kotlin/dynamicServer.kt new file mode 100644 index 00000000..0d374447 --- /dev/null +++ b/plotly/examples/src/main/kotlin/dynamicServer.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/embededFileExport.kt b/plotly/examples/src/main/kotlin/embededFileExport.kt new file mode 100644 index 00000000..5e72482a --- /dev/null +++ b/plotly/examples/src/main/kotlin/embededFileExport.kt @@ -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) +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/errorPlots/AssymetricErrorBars.kt b/plotly/examples/src/main/kotlin/errorPlots/AssymetricErrorBars.kt new file mode 100644 index 00000000..1ee63bd8 --- /dev/null +++ b/plotly/examples/src/main/kotlin/errorPlots/AssymetricErrorBars.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/errorPlots/BarChartWithErrorBars.kt b/plotly/examples/src/main/kotlin/errorPlots/BarChartWithErrorBars.kt new file mode 100644 index 00000000..0b140e6d --- /dev/null +++ b/plotly/examples/src/main/kotlin/errorPlots/BarChartWithErrorBars.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/errorPlots/BasicSymmetricErrorBars.kt b/plotly/examples/src/main/kotlin/errorPlots/BasicSymmetricErrorBars.kt new file mode 100644 index 00000000..d41f3540 --- /dev/null +++ b/plotly/examples/src/main/kotlin/errorPlots/BasicSymmetricErrorBars.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/errorPlots/ColoredBoxPlot.kt b/plotly/examples/src/main/kotlin/errorPlots/ColoredBoxPlot.kt new file mode 100644 index 00000000..791273c2 --- /dev/null +++ b/plotly/examples/src/main/kotlin/errorPlots/ColoredBoxPlot.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/errorPlots/FillLines.kt b/plotly/examples/src/main/kotlin/errorPlots/FillLines.kt new file mode 100644 index 00000000..d9978cda --- /dev/null +++ b/plotly/examples/src/main/kotlin/errorPlots/FillLines.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/errorPlots/RandomDataErrorsX.kt b/plotly/examples/src/main/kotlin/errorPlots/RandomDataErrorsX.kt new file mode 100644 index 00000000..59599e35 --- /dev/null +++ b/plotly/examples/src/main/kotlin/errorPlots/RandomDataErrorsX.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/functionTraces.kt b/plotly/examples/src/main/kotlin/functionTraces.kt new file mode 100644 index 00000000..45efb806 --- /dev/null +++ b/plotly/examples/src/main/kotlin/functionTraces.kt @@ -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() +} diff --git a/plotly/examples/src/main/kotlin/geo/choropleth.kt b/plotly/examples/src/main/kotlin/geo/choropleth.kt new file mode 100644 index 00000000..8648e2d2 --- /dev/null +++ b/plotly/examples/src/main/kotlin/geo/choropleth.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/geo/dynamicMap.kt b/plotly/examples/src/main/kotlin/geo/dynamicMap.kt new file mode 100644 index 00000000..d3151cf6 --- /dev/null +++ b/plotly/examples/src/main/kotlin/geo/dynamicMap.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/geo/saxony.kt b/plotly/examples/src/main/kotlin/geo/saxony.kt new file mode 100644 index 00000000..55c18770 --- /dev/null +++ b/plotly/examples/src/main/kotlin/geo/saxony.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/geo/scattermapbox.kt b/plotly/examples/src/main/kotlin/geo/scattermapbox.kt new file mode 100644 index 00000000..9cd7b5dc --- /dev/null +++ b/plotly/examples/src/main/kotlin/geo/scattermapbox.kt @@ -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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/gridPageLayout.kt b/plotly/examples/src/main/kotlin/gridPageLayout.kt new file mode 100644 index 00000000..d87a8409 --- /dev/null +++ b/plotly/examples/src/main/kotlin/gridPageLayout.kt @@ -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() + + /** + * @return Columns in ascending order, grouped by rows in ascending order. + * */ + public val grid: List> + 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() +} diff --git a/plotly/examples/src/main/kotlin/heatmap/AnnotatedHeatmap.kt b/plotly/examples/src/main/kotlin/heatmap/AnnotatedHeatmap.kt new file mode 100644 index 00000000..2f279540 --- /dev/null +++ b/plotly/examples/src/main/kotlin/heatmap/AnnotatedHeatmap.kt @@ -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>() + + for (i in y1.indices) { + z1.add(MutableList(x1.size) { 0.0 }) + } + + val annotationsList = mutableListOf() + + 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() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/heatmap/AxisTitles.kt b/plotly/examples/src/main/kotlin/heatmap/AxisTitles.kt new file mode 100644 index 00000000..c9fb6aa0 --- /dev/null +++ b/plotly/examples/src/main/kotlin/heatmap/AxisTitles.kt @@ -0,0 +1,55 @@ +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.palettes.Xkcd + + +/** + * - Heatmap with custom colorscale + * - Add axis label + * - Use XKCD color palette + * - Change size of the plot + */ +fun main() { + val months = listOf("January", "February", "March", "April", "May", "June", "July", "August", + "September", "October", "November", "December") + val years = 1949..1961 + val flights = listOf( + listOf(112, 115, 145, 171, 196, 204, 242, 284, 315, 340, 360, 417), /* January */ + listOf(118, 126, 150, 180, 196, 188, 233, 277, 301, 318, 342, 391), /* February */ + listOf(132, 141, 178, 193, 236, 235, 267, 317, 356, 362, 406, 419), /* March */ + listOf(129, 135, 163, 181, 235, 227, 269, 313, 348, 348, 396, 461), /* April */ + listOf(121, 125, 172, 183, 229, 234, 270, 318, 355, 363, 420, 472), /* May */ + listOf(135, 149, 178, 218, 243, 264, 315, 374, 422, 435, 472, 535), /* June */ + listOf(148, 170, 199, 230, 264, 302, 364, 413, 465, 491, 548, 622), /* July */ + listOf(148, 170, 199, 242, 272, 293, 347, 405, 467, 505, 559, 606), /* August */ + listOf(136, 158, 184, 209, 237, 259, 312, 355, 404, 404, 463, 508), /* September */ + listOf(119, 133, 162, 191, 211, 229, 274, 306, 347, 359, 407, 461), /* October */ + listOf(104, 114, 146, 172, 180, 203, 237, 271, 305, 310, 362, 390), /* November */ + listOf(118, 140, 166, 194, 201, 229, 278, 306, 336, 337, 405, 432) /* December */) + val customColorscale = listOf(listOf(0, Xkcd.POWDER_BLUE), listOf(1, Xkcd.PURPLE)) + + val plot = Plotly.plot { + heatmap { + x.set(years) + y.set(months) + z.set(flights) + colorscale = Value.of(customColorscale) + } + + layout { + width = 900 + height = 900 + xaxis { + title = "Years" + } + title = "Heatmap of Flight Density from 1949 to 1961" + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/heatmap/BasicHeatmap.kt b/plotly/examples/src/main/kotlin/heatmap/BasicHeatmap.kt new file mode 100644 index 00000000..5e8863c1 --- /dev/null +++ b/plotly/examples/src/main/kotlin/heatmap/BasicHeatmap.kt @@ -0,0 +1,34 @@ +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 + + +/** + * - basic heatmap from 1 to 25 + * - change heatmap colorscale + * - use 2D array as z + */ +fun main() { + val x1 = listOf(1, 2, 3, 4, 5) + val y1 = listOf(6, 7, 8, 9, 10) + val z1 = (1..25).chunked(5) + + val plot = Plotly.plot { + heatmap { + x.set(x1) + y.set(y1) + z.set(z1) + colorscale = Value.of("Reds") + } + + layout { + title = "Red Heatmap" + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/heatmap/CategoricalAxisLabels.kt b/plotly/examples/src/main/kotlin/heatmap/CategoricalAxisLabels.kt new file mode 100644 index 00000000..1b0038e3 --- /dev/null +++ b/plotly/examples/src/main/kotlin/heatmap/CategoricalAxisLabels.kt @@ -0,0 +1,49 @@ +package heatmap + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.heatmap +import space.kscience.plotly.makeFile + + +/** + * - Annotated heatmap with categorical labels + * - change size of labels font + * - rotate axis labels + */ +fun main() { + val x1 = listOf("Monday", "Tuesday", "Wednesday", "Thursday", "Friday") + val y1 = listOf("Morning", "Afternoon", "Evening") + val z1 = listOf( + listOf(1, null, 30, 50, 1), + listOf(20, 1, 60, 80, 30), + listOf(30, 60, 1, -10, 20)) + + val plot = Plotly.plot { + heatmap { + x.set(x1) + y.set(y1) + z.set(z1) + } + + layout { + xaxis { + tickfont { + size = 16 + } + } + yaxis { + tickangle = -90 + tickfont { + size = 16 + } + } + title { + text = "Heatmap with Categorical Axis Labels" + font { size = 20 } + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/heatmap/ConnectNullGaps.kt b/plotly/examples/src/main/kotlin/heatmap/ConnectNullGaps.kt new file mode 100644 index 00000000..1db08e32 --- /dev/null +++ b/plotly/examples/src/main/kotlin/heatmap/ConnectNullGaps.kt @@ -0,0 +1,59 @@ +package heatmap + +import space.kscience.plotly.* +import space.kscience.plotly.models.Heatmap + + +/** + * - heatmaps 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(null, null, null, 12, 13, 14, 15, 16), + listOf(null, 1, null, 11, null, null, null, 17), + listOf(null, 2, 6, 7, null, null, null, 18), + listOf(null, 3, null, 8, null, null, null, 19), + listOf(5, 4, 10, 9, null, null, null, 20), + listOf(null, null, null, 27, null, null, null, 21), + listOf(null, null, null, 26, 25, 24, 23, 22)) + + val heatmap1 = Heatmap { + x.set(x1) + y.set(y2) + z.set(z1) + showscale = false + } + + val heatmap2 = Heatmap { + x.set(x1) + y.set(y2) + z.set(z1) + showscale = false + connectgaps = true + } + + Plotly.fragment { + plot { + traces(heatmap1) + layout { + width = 800 + height = 450 + title = "Gaps Between Nulls" + } + } + + plot { + traces(heatmap2) + layout { + width = 800 + height = 450 + title = "Connected Gaps" + } + } + }.makeFile() +} diff --git a/plotly/examples/src/main/kotlin/heatmap/CustomColorscale.kt b/plotly/examples/src/main/kotlin/heatmap/CustomColorscale.kt new file mode 100644 index 00000000..e2e953e2 --- /dev/null +++ b/plotly/examples/src/main/kotlin/heatmap/CustomColorscale.kt @@ -0,0 +1,71 @@ +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 + +/** + * - Simple heatmap with annotations + * - Change annotation font color anf size + * - Use custom colorscale + */ +fun main() { + val x1 = listOf("Monday", "Wednesday", "Friday", "Sunday") + val y1 = listOf("June", "July", "August") + val z1 = listOf( + listOf(.1, .3, .5, .7), + listOf(1.0, .8, .6, .4), + listOf(.6, .4, .2, 0.0), + listOf(.9, .7, .5, .3)) + val customColorscale = listOf(listOf(0, "navy"), listOf(1, "plum")) + + val annotationsList = mutableListOf() + val annotationFont = Font() + annotationFont.color("white") + annotationFont.size = 16 + for (i in y1.indices) { + for (j in x1.indices) { + val curAnnotation = Text() + curAnnotation.font = annotationFont + curAnnotation.x = Value.of(x1[j]) + curAnnotation.y = Value.of(y1[i]) + curAnnotation.text = z1[i][j].toString() + curAnnotation.showarrow = false + annotationsList.add(curAnnotation) + } + } + + val plot = Plotly.plot { + heatmap { + x.set(x1) + y.set(y1) + z(z1) + + colorscale = Value.of(customColorscale) + colorbar { + tickfont { size = 16 } + } + } + + layout { + xaxis { + tickfont { size = 16 } + } + yaxis { + tickfont { size = 16 } + tickangle = -45 + } + annotations = annotationsList + title { + text = "Heatmap with Custom Colorscale" + font { size = 20 } + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/histogram/2DContourHistogram.kt b/plotly/examples/src/main/kotlin/histogram/2DContourHistogram.kt new file mode 100644 index 00000000..19f103c8 --- /dev/null +++ b/plotly/examples/src/main/kotlin/histogram/2DContourHistogram.kt @@ -0,0 +1,51 @@ +package histogram + +import space.kscience.dataforge.meta.Value +import space.kscience.plotly.Plotly +import space.kscience.plotly.layout +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.ContoursColoring +import space.kscience.plotly.models.Histogram2DContour +import space.kscience.plotly.models.MeasureMode + + +/** + * - 2D contour histogram of a bivariate distribution + * - change histogram colorscale + * - change colorbar thickness and thickness mode + * - change width of the colorbar border + * - change contours coloring + */ +fun main() { + val x1 = mutableListOf() + val y1 = mutableListOf() + + for (i in 0 until 500) { + x1.add(Math.random()) + y1.add(Math.random()) + } + + val trace = Histogram2DContour { + x.set(x1) + y.set(y1) + colorscale = Value.of("Greens") + contours { + coloring = ContoursColoring.heatmap + } + colorbar { + borderwidth = 0 + thicknessmode = MeasureMode.fraction + thickness = 0.05 + } + } + + val plot = Plotly.plot { + traces(trace) + + layout { + title = "2D Contour Histogram of a Bivariate Normal Distribution" + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/histogram/BasicHistogram.kt b/plotly/examples/src/main/kotlin/histogram/BasicHistogram.kt new file mode 100644 index 00000000..a64f0d5a --- /dev/null +++ b/plotly/examples/src/main/kotlin/histogram/BasicHistogram.kt @@ -0,0 +1,55 @@ +package histogram + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.histogram +import space.kscience.plotly.makeFile +import java.util.* + + +/** + * - basic histogram + * - change size of gap between bins + * - change font color and size of title + * - change font size of axis title + */ +fun main() { + val rnd = Random() + val values = List(500) { rnd.nextDouble() } + + val plot = Plotly.plot { + histogram { + x.numbers = values + name = "Random data" + } + + 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 + } + } + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/histogram/ColoredAndStyledHistogram.kt b/plotly/examples/src/main/kotlin/histogram/ColoredAndStyledHistogram.kt new file mode 100644 index 00000000..16390ce2 --- /dev/null +++ b/plotly/examples/src/main/kotlin/histogram/ColoredAndStyledHistogram.kt @@ -0,0 +1,75 @@ +package histogram + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.* +import java.util.* + +/** + * - overlaying histograms + * - use RGBA as color palette + * - change bargap, bargroupgap, barmode parameters + */ +fun main() { + val rnd = Random() + val k = List(500) { rnd.nextDouble() } + + val trace1 = Histogram { + x.numbers = k.map { it * 5 } + y.numbers = k.map { it } + name = "control" + histfunc = HistFunc.count + marker { + color(255, 50, 102, 0.7) + } + opacity = 0.5 + xbins { + end = 2.8 + start = 0.5 + size = 0.06 + } + } + + val trace2 = Histogram { + x.numbers = k.map { it * 10 } + y.numbers = k.map { it*2 } + name = "experimental" + marker { + color(0, 100, 255, 0.7) + } + opacity = 0.75 + xbins { + end = 4.0 + start = -3.2 + size = 0.06 + } + } + + val plot = Plotly.plot { + traces(trace1, trace2) + layout { + width = 900 + height = 500 + bargap = 0.05 + bargroupgap = 0.2 + barmode = BarMode.overlay + title = "Sampled Results" + xaxis { + title = "Value" + } + yaxis { + title = "Count" + } + legend { + x = 1 + y = 1 + xanchor = XAnchor.auto + bgcolor("#E2E2E2") + traceorder = TraceOrder.normal + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/histogram/CumulativeHistogram.kt b/plotly/examples/src/main/kotlin/histogram/CumulativeHistogram.kt new file mode 100644 index 00000000..5fd8d558 --- /dev/null +++ b/plotly/examples/src/main/kotlin/histogram/CumulativeHistogram.kt @@ -0,0 +1,45 @@ +package histogram + +import space.kscience.plotly.Plotly +import space.kscience.plotly.histogram +import space.kscience.plotly.layout +import space.kscience.plotly.makeFile +import space.kscience.plotly.palettes.T10 +import java.util.* + + +/** + * - cumulative histogram + * - use Tableau10 as color palette + */ +fun main() { + val rnd = Random() + val values = List(500) { rnd.nextDouble() } + + val plot = Plotly.plot { + histogram { + x.numbers = values + name = "Random data" + + cumulative { + enabled = true + } + + marker { + color(T10.CYAN) + } + } + + layout { + title = "Cumulative Histogram" + xaxis { + title = "Value" + } + yaxis { + title = "Sum of probabilities" + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/histogram/HorizontalHistogram.kt b/plotly/examples/src/main/kotlin/histogram/HorizontalHistogram.kt new file mode 100644 index 00000000..7134a052 --- /dev/null +++ b/plotly/examples/src/main/kotlin/histogram/HorizontalHistogram.kt @@ -0,0 +1,46 @@ +package histogram + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.histogram +import space.kscience.plotly.makeFile +import space.kscience.plotly.palettes.T10 + + +/** + * - horizontal histogram: count entries of each value + * ([1, 2, 2, 3, 2, 1, 4, 4] -> [1: 2, 2: 3, 3: 1, 4: 2]) + * - use T10 as color palette (default color circle) + * - use color array + * - white ticks as space between axis and labels + * - change ticklen, tickcolor parameters + */ +fun main() { + val values = listOf(1, 2, 2, 3, 2, 1, 4, 4) + val colors = listOf(T10.RED, T10.GREEN, T10.ORANGE, T10.BLUE) + + val plot = Plotly.plot { + histogram { + name = "Random data" + y.set(values) + marker { + colors(colors) + } + } + + layout { + title = "Horizontal Histogram" + bargap = 0.1 + xaxis { + title = "Count" + } + yaxis { + title = "Value" + ticklen = 3 + tickcolor("#FFF") + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/histogram/NormalizedHistogram.kt b/plotly/examples/src/main/kotlin/histogram/NormalizedHistogram.kt new file mode 100644 index 00000000..f400b640 --- /dev/null +++ b/plotly/examples/src/main/kotlin/histogram/NormalizedHistogram.kt @@ -0,0 +1,47 @@ +package histogram + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.histogram +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.HistNorm +import space.kscience.plotly.palettes.Xkcd +import kotlin.random.Random + +/** + * - normalized histogram: the counts normalized to form a probability density, + * i.e., the area (or integral) under the histogram will sum to 1. + * - change size of gap between bins + * - change font size of tick labels + */ +fun main() { + val x1 = List(500) { Random.nextDouble() } + + val plot = Plotly.plot { + histogram { + x.numbers = x1 + name = "Random data" + histnorm = HistNorm.probability + marker { + color(Xkcd.BLUE_GREEN) + } + } + + layout { + title = "Normalized Histogram" + bargap = 0.1 + xaxis { + tickfont { + size = 16 + } + } + yaxis { + tickfont { + size = 16 + } + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/histogram/OverlaidHistogram.kt b/plotly/examples/src/main/kotlin/histogram/OverlaidHistogram.kt new file mode 100644 index 00000000..8b7dfecb --- /dev/null +++ b/plotly/examples/src/main/kotlin/histogram/OverlaidHistogram.kt @@ -0,0 +1,55 @@ +package histogram + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.BarMode +import space.kscience.plotly.models.Histogram +import space.kscience.plotly.palettes.T10 +import java.util.* + +/** + * - overlaying histograms + * - use T10 as color palette + * - change legend font size and color + */ +fun main() { + val rnd = Random() + val k = List(500) { rnd.nextDouble() } + val x1 = k.map { it + 1 }.toList() + val x2 = k.map { it + 1.1 }.toList() + + val trace1 = Histogram { + x.set(x1) + opacity = 0.5 + marker { + color(T10.BLUE) + } + } + + val trace2 = Histogram { + x.set(x2) + opacity = 0.6 + marker { + color(T10.PINK) + } + } + + val plot = Plotly.plot { + traces(trace1, trace2) + layout { + title = "Overlaid Histogram" + barmode = BarMode.overlay + bargap = 0.1 + + legend { + font { + size = 16 + color("black") + } + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/histogram/SpecifyBinningHistogram.kt b/plotly/examples/src/main/kotlin/histogram/SpecifyBinningHistogram.kt new file mode 100644 index 00000000..05fbe570 --- /dev/null +++ b/plotly/examples/src/main/kotlin/histogram/SpecifyBinningHistogram.kt @@ -0,0 +1,48 @@ +package histogram + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.histogram +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.HistFunc +import space.kscience.plotly.models.XAnchor + + +/** + * - defferent binning functions + * - default color cycle + * - change legend border width + */ +fun main() { + val categories = listOf("Apples", "Apples", "Apples", "Oranges", "Bananas") + val values = listOf("5", "10", "3", "10", "5") + + val plot = Plotly.plot { + histogram { + name = "count" + x.strings = categories + y.strings = values + histfunc = HistFunc.count + } + + histogram { + name = "sum" + x.strings = categories + y.strings = values + histfunc = HistFunc.sum + } + + layout { + width = 750 + title = "Specify Binning Function" + legend { + x = 1 + y = 1 + xanchor = XAnchor.auto + borderwidth = 1 + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/histogram/StackedHistogram.kt b/plotly/examples/src/main/kotlin/histogram/StackedHistogram.kt new file mode 100644 index 00000000..22c6fb09 --- /dev/null +++ b/plotly/examples/src/main/kotlin/histogram/StackedHistogram.kt @@ -0,0 +1,42 @@ +package histogram + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.BarMode +import space.kscience.plotly.models.Histogram +import java.util.* + + +fun main() { + val rnd = Random() + val k = List(500) { rnd.nextDouble() } + val x1 = k.map { it }.toList() + val x2 = k.map { it / 2 }.toList() + + val trace1 = Histogram { + x.set(x1) + opacity = 0.5 + marker { + color("green") + } + } + + val trace2 = Histogram { + x.set(x2) + opacity = 0.5 + marker { + color("orange") + } + } + + val plot = Plotly.plot { + traces(trace1, trace2) + layout { + title = "Stacked Histogram" + barmode = BarMode.stack + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/io/ioUtils.kt b/plotly/examples/src/main/kotlin/io/ioUtils.kt new file mode 100644 index 00000000..b84059a1 --- /dev/null +++ b/plotly/examples/src/main/kotlin/io/ioUtils.kt @@ -0,0 +1,30 @@ +package io + + +import org.jetbrains.kotlinx.dataframe.AnyCol +import org.jetbrains.kotlinx.dataframe.AnyFrame +import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.io.readCSV +import space.kscience.dataforge.meta.Value +import space.kscience.plotly.Plotly +import space.kscience.plotly.models.TraceValues + +fun readResourceAsString(resource: String): String = + Plotly.javaClass.getResourceAsStream(resource)?.readAllBytes()?.decodeToString() + ?: error("Resource $resource not found") + +fun readResourceAsCsv(resource: String): AnyFrame = + DataFrame.readCSV(Plotly.javaClass.getResource(resource)?.file?.toString() ?: error("Resource $resource not found")) + +/** + * Extension function for using krangl data columns as axis values + */ +operator fun TraceValues.invoke(column: AnyCol) { + set(column.values()) +} + +fun TraceValues.fromDataFrame(frame: AnyFrame, column: String) { + invoke(frame[column]) +} + +fun AnyCol.dfValues(): List = values().map { Value.of(it) } \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/io/loadFromResource.kt b/plotly/examples/src/main/kotlin/io/loadFromResource.kt new file mode 100644 index 00000000..ef883606 --- /dev/null +++ b/plotly/examples/src/main/kotlin/io/loadFromResource.kt @@ -0,0 +1,30 @@ +package io + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.ScatterMode +import space.kscience.plotly.scatter + + +fun main() { + val resource = readResourceAsString("/simpleData.txt") + + val data = resource.lines().map { it.split(" ").map { it.toInt() } } + + val plot = Plotly.plot { + scatter { + x.numbers = data[0] + y.numbers = data[1] + mode = ScatterMode.markers + } + + layout { + title { + text = "Load from resource" + } + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/latexLabels.kt b/plotly/examples/src/main/kotlin/latexLabels.kt new file mode 100644 index 00000000..85f767fd --- /dev/null +++ b/plotly/examples/src/main/kotlin/latexLabels.kt @@ -0,0 +1,34 @@ +import space.kscience.plotly.* + +fun main() { + Plotly.page(mathJaxHeader, cdnPlotlyHeader) { + plot { + scatter { + x(2, 3, 4, 5) + y(10, 15, 13, 17) + } + + text { + position(2, 10) + font { + size = 18 + } + text = "\$\\alpha\$" + } + + text { + position(5, 17) + font { + size = 18 + } + text = "\$\\Omega\$" + } + + layout { + title { + text = "Plot with annotations \$\\alpha~and~\\Omega\$" + } + } + } + }.makeFile() +} diff --git a/plotly/examples/src/main/kotlin/localFileExport.kt b/plotly/examples/src/main/kotlin/localFileExport.kt new file mode 100644 index 00000000..dd293598 --- /dev/null +++ b/plotly/examples/src/main/kotlin/localFileExport.kt @@ -0,0 +1,30 @@ +import space.kscience.plotly.* +import kotlin.math.PI +import kotlin.math.sin + + +@UnstablePlotlyAPI +fun main() { + val xValues = (0..100).map { it.toDouble() / 100.0 } + val yValues = xValues.map { sin(2.0 * PI * it) } + + val plot = Plotly.plot { + trace { + x.set(xValues) + y.set(yValues) + 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(selectFile()) + //plot.makeFile(Files.createTempFile("plotlykt",".html")) +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/misc/dynamicBars.kt b/plotly/examples/src/main/kotlin/misc/dynamicBars.kt new file mode 100644 index 00000000..fe0ad8f1 --- /dev/null +++ b/plotly/examples/src/main/kotlin/misc/dynamicBars.kt @@ -0,0 +1,63 @@ +import kotlinx.coroutines.* +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.models.Bar +import space.kscience.plotly.server.* +import kotlin.random.Random + + +@OptIn(DelicateCoroutinesApi::class) +fun main() { + val initialValue = (1..10).toList() + + val traces = (0..2).associate { i -> + val name = "Series $i" + + name to Bar { + x.strings = initialValue.map { "Column: $it" } + y.numbers = initialValue + text.strings = initialValue.map { "Initial value of this datapoint is: ${it}" } + this.name = name + } + } + + val server = Plotly.serve(port = 3872) { + pushUpdates(200) + //root level plots go to default page + plot { + traces(traces.values) + layout { + title = "Other dynamic plot" + xaxis.title = "x axis name" + yaxis.title = "y axis name" + } + } + } + + server.show() + + //Start pushing updates + GlobalScope.launch { + delay(1000) + while (isActive) { + repeat(10) { columnIndex -> + repeat(3) { seriesIndex -> + delay(200) + traces["Series $seriesIndex"]?.let { bar -> + println("Updating ${bar.name}, Column $columnIndex") + //TODO replace with dynamic data API + val yValues = bar.y.doubles + yValues[columnIndex] = Random.nextInt(0, 100).toDouble() + bar.y.doubles = yValues + bar.text.strings = yValues.map { "Updated value of this datapoint is: $it" } + } + } + } + } + } + + println("Press Enter to close server") + readLine() + + server.close() +} diff --git a/plotly/examples/src/main/kotlin/misc/dynamicHistogram.kt b/plotly/examples/src/main/kotlin/misc/dynamicHistogram.kt new file mode 100644 index 00000000..b2335002 --- /dev/null +++ b/plotly/examples/src/main/kotlin/misc/dynamicHistogram.kt @@ -0,0 +1,61 @@ +package misc + +import kotlinx.coroutines.* +import space.kscience.plotly.Plotly +import space.kscience.plotly.histogram +import space.kscience.plotly.layout +import space.kscience.plotly.server.close +import space.kscience.plotly.server.plot +import space.kscience.plotly.server.serve +import kotlin.random.Random + +@OptIn(DelicateCoroutinesApi::class) +fun main() { + val server = Plotly.serve { + val rnd = Random(222) + plot { + 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 + } + } + } + } + } + } + + println("Press Enter to close server") + readLine() + + server.close() + +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/misc/layoutImages.kt b/plotly/examples/src/main/kotlin/misc/layoutImages.kt new file mode 100644 index 00000000..55684d29 --- /dev/null +++ b/plotly/examples/src/main/kotlin/misc/layoutImages.kt @@ -0,0 +1,39 @@ +package misc + +import space.kscience.plotly.Plotly +import space.kscience.plotly.layout +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.ImageXAnchor +import space.kscience.plotly.models.ImageYAnchor +import space.kscience.plotly.scatter + +fun main() { + Plotly.plot { + scatter { + x(1, 2, 3) + y(1, 2, 3) + } + layout { + image { + source = "https://images.plot.ly/language-icons/api-home/python-logo.png" + x = 0.0 + y = 1.0 + sizex = 0.2 + sizey = 0.2 + xanchor = ImageXAnchor.right + yanchor = ImageYAnchor.bottom + } + image { + source = "https://images.plot.ly/language-icons/api-home/js-logo.png" + xref = "x" + yref = "y" + x = 1.5 + y = 2.0 + sizex = 1.0 + sizey = 1.0 + xanchor = ImageXAnchor.right + yanchor = ImageYAnchor.bottom + } + } + }.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/misc/secondaryYAxis.kt b/plotly/examples/src/main/kotlin/misc/secondaryYAxis.kt new file mode 100644 index 00000000..01e30a9c --- /dev/null +++ b/plotly/examples/src/main/kotlin/misc/secondaryYAxis.kt @@ -0,0 +1,46 @@ +package misc + +import space.kscience.plotly.Plotly +import space.kscience.plotly.layout +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.AxisSide +import space.kscience.plotly.scatter + + +fun main() { + Plotly.plot { + + scatter { + x(1, 2, 3) + y(40, 50, 60) + name = "yaxis data" + } + + scatter { + x(2, 3, 4) + y(4, 5, 6) + name = "yaxis2 data" + yaxis = "y2" + } + + layout { + title = "Double Y Axis Example" + yaxis { + title = "yaxis title" + } + yaxis(2) { + title { + text = "yaxis2 title" + font { + color("rgb(148, 103, 189)") + } + } + tickfont { + color("rgb(148, 103, 189)") + } + overlaying = "y" + side = AxisSide.right + } + } + }.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/misc/singleValue.kt b/plotly/examples/src/main/kotlin/misc/singleValue.kt new file mode 100644 index 00000000..ce1346b5 --- /dev/null +++ b/plotly/examples/src/main/kotlin/misc/singleValue.kt @@ -0,0 +1,15 @@ +package misc + +import space.kscience.plotly.Plotly +import space.kscience.plotly.bar +import space.kscience.plotly.makeFile + +fun main() { + val plot = Plotly.plot { + bar { + x("giraffes") + y(20) + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/pie/BasicPieChart.kt b/plotly/examples/src/main/kotlin/pie/BasicPieChart.kt new file mode 100644 index 00000000..31502262 --- /dev/null +++ b/plotly/examples/src/main/kotlin/pie/BasicPieChart.kt @@ -0,0 +1,30 @@ +package pie + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.Pie + +/** + * - basic pie chart + * - change height and width of the plot + */ +fun main() { + val values = listOf(19, 26, 55) + val labels = listOf("Residential", "Non-Residential", "Utility") + + val pie = Pie { + values(values) + labels(labels) + } + + val plot = Plotly.plot { + traces(pie) + layout { + width = 500 + height = 450 + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/pie/DonutChart.kt b/plotly/examples/src/main/kotlin/pie/DonutChart.kt new file mode 100644 index 00000000..84d3f3e2 --- /dev/null +++ b/plotly/examples/src/main/kotlin/pie/DonutChart.kt @@ -0,0 +1,45 @@ +package pie + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.fragment +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.Pie +import space.kscience.plotly.plot + + +fun main() { + val donut1 = Pie { + values(listOf(16, 15, 12, 6, 5, 4, 42)) + labels(listOf("US", "China", "European Union", "Russian Federation", "Brazil", "India", "Rest of World")) + hole = 0.4 + } + + val donut2 = Pie { + values(listOf(27, 11, 25, 8, 1, 3, 25)) + labels(listOf("US", "China", "European Union", "Russian Federation", "Brazil", "India", "Rest of World")) + hole = 0.4 + } + + Plotly.fragment { + plot { + traces(donut1) + + layout { + width = 600 + height = 600 + title = "GHG Emissions" + } + } + + plot { + traces(donut2) + + layout { + width = 600 + height = 600 + title = "CO2" + } + } + }.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/pie/ManyTracesChart.kt b/plotly/examples/src/main/kotlin/pie/ManyTracesChart.kt new file mode 100644 index 00000000..9b7bba32 --- /dev/null +++ b/plotly/examples/src/main/kotlin/pie/ManyTracesChart.kt @@ -0,0 +1,89 @@ +package pie + +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.Pie +import space.kscience.plotly.models.TextInfo + + +/** + * - Pie chart with many traces + * - Use colors array as pieColors + * - Change trace domain + */ +fun main() { + val allLabels = listOf("1st", "2nd", "3rd", "4th", "5th") + val allValues = listOf( + listOf(38, 27, 18, 10, 7), + listOf(28, 26, 21, 15, 10), + listOf(38, 19, 16, 14, 13), + listOf(31, 24, 19, 18, 8)) + val ultimateColors = listOf( + listOf("rgb(56, 75, 126)", "rgb(18, 36, 37)", "rgb(34, 53, 101)", "rgb(36, 55, 57)", "rgb(6, 4, 4)"), + listOf("rgb(177, 127, 38)", "rgb(205, 152, 36)", "rgb(99, 79, 37)", "rgb(129, 180, 179)", "rgb(124, 103, 37)"), + listOf("rgb(33, 75, 99)", "rgb(79, 129, 102)", "rgb(151, 179, 100)", "rgb(175, 49, 35)", "rgb(36, 73, 147)"), + listOf("rgb(146, 123, 21)", "rgb(177, 180, 34)", "rgb(206, 206, 40)", "rgb(175, 51, 21)", "rgb(35, 36, 21)")) + + val pie1 = Pie { + values = allValues[0].map { Value.of(it) } + labels = allLabels.map { Value.of(it) } + name = "Starry Night" + marker { pieColors = ultimateColors[0].map { Value.of(it) } } + domain { + x = listOf(0, 0.48) + y = listOf(0, 0.48) + } + hoverinfo = "label+percent+name" + textinfo = TextInfo.none + } + val pie2 = Pie { + values = allValues[1].map { Value.of(it) } + labels = allLabels.map { Value.of(it) } + name = "Sunflowers" + marker { pieColors = ultimateColors[1].map { Value.of(it) } } + domain { + x = listOf(0, 0.48) + y = listOf(0.52, 1) + } + hoverinfo = "label+percent+name" + textinfo = TextInfo.none + } + val pie3 = Pie { + values = allValues[2].map { Value.of(it) } + labels = allLabels.map { Value.of(it) } + name = "Irises" + marker { pieColors = ultimateColors[2].map { Value.of(it) } } + domain { + x = listOf(0.52, 1) + y = listOf(0, 0.48) + } + hoverinfo = "label+percent+name" + textinfo = TextInfo.none + } + val pie4 = Pie { + values = allValues[3].map { Value.of(it) } + labels = allLabels.map { Value.of(it) } + name = "The Night Cafe" + marker { pieColors = ultimateColors[3].map { Value.of(it) } } + domain { + x = listOf(0.52, 1) + y = listOf(0.52, 1) + } + hoverinfo = "label+percent+name" + textinfo = TextInfo.none + } + + val plot = Plotly.plot { + traces(pie1, pie2, pie3, pie4) + + layout { + title = "Pie Chart With Many Traces" + height = 500 + width = 500 + showlegend = false + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/pie/NestedPieChart.kt b/plotly/examples/src/main/kotlin/pie/NestedPieChart.kt new file mode 100644 index 00000000..954c8d5b --- /dev/null +++ b/plotly/examples/src/main/kotlin/pie/NestedPieChart.kt @@ -0,0 +1,78 @@ +package pie + +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.Pie +import space.kscience.plotly.palettes.Xkcd + + +/** + * - Nested pie chart + * - Set sectors colors using marker -> colors + * - Change legend borderwidth + */ +fun main() { + val labels = listOf("party A", "party B", "party C", "party D") + val colorsPie = listOf(Xkcd.RED, Xkcd.GREEN, Xkcd.ORANGE, Xkcd.BLUE).map { Value.of(it) } + + val firstPie = Pie { + name = "First day" + values(listOf(3, 2, 2, 3)) + labels(labels) + hole = 0.5 + sort = false + textfont { size = 16 } + domain { + x = listOf(0.2, 0.8) + y = listOf(0.1, 0.9) + } + marker { + pieColors = colorsPie + line { + color("white") + width = 2 + } + } + } + + val secondPie = Pie { + name = "Second day" + values(listOf(8, 7, 6, 5)) + labels(labels) + hole = 0.77 + opacity = 0.75 + sort = false + textfont { size = 16 } + domain { + x = listOf(0.1, 0.9) + y = listOf(0, 1) + } + marker { + pieColors = colorsPie + line { + color("white") + width = 2 + } + } + } + + val plot = Plotly.plot { + traces(firstPie, secondPie) + + layout { + width = 700 + height = 600 + title = "Nested Pie Charts" + + legend { + borderwidth = 1 + font { + size = 16 + } + } + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/pie/OnlyLegendLabels.kt b/plotly/examples/src/main/kotlin/pie/OnlyLegendLabels.kt new file mode 100644 index 00000000..b207cc12 --- /dev/null +++ b/plotly/examples/src/main/kotlin/pie/OnlyLegendLabels.kt @@ -0,0 +1,33 @@ +package pie + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.TextInfo +import space.kscience.plotly.pie + +fun main() { + val labels = listOf("Cookies", "Jellybean", "Milkshake", "Cheesecake") + val values = listOf(38.4, 40.6, 20.7, 10.3) + + val plot = Plotly.plot { + pie { + labels(labels) + values(values) + textinfo = TextInfo.none + } + + layout { + width = 700 + height = 600 + title = "Show Labels Only in Legend" + legend { + borderwidth = 1 + font { + size = 16 + } + } + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/pie/PullSectorPie.kt b/plotly/examples/src/main/kotlin/pie/PullSectorPie.kt new file mode 100644 index 00000000..a41da970 --- /dev/null +++ b/plotly/examples/src/main/kotlin/pie/PullSectorPie.kt @@ -0,0 +1,42 @@ +package pie + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.TextInfo +import space.kscience.plotly.models.TextPosition +import space.kscience.plotly.pie + + +/** + * - Pie chart with pulled out sector + * - Change start angle of pie + * - Show labels outside the pie + */ +fun main() { + val labels = listOf("Python", "C++", "Ruby", "Java") + val values = listOf(215, 130, 245, 210) + val pullSectors = listOf(0.1, 0, 0, 0) + + val plot = Plotly.plot { + pie { + labels(labels) + values(values) + pullList = pullSectors + rotation = -45 + textposition = TextPosition.outside + textinfo = TextInfo.`label+percent` + textfont { + size = 16 + } + showlegend = false + } + + layout { + height = 600 + width = 700 + title = "Pull Sector Pie Chart" + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/plots3d/scatter3d.kt b/plotly/examples/src/main/kotlin/plots3d/scatter3d.kt new file mode 100644 index 00000000..39143a79 --- /dev/null +++ b/plotly/examples/src/main/kotlin/plots3d/scatter3d.kt @@ -0,0 +1,19 @@ +package plots3d + +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.TraceType +import space.kscience.plotly.trace + + +fun main() { + val plot = Plotly.plot { + trace { + type = TraceType.scatter3d + x(1,2,3) + y(1,2,3) + z(1,2,3) + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/plots3d/surface3d.kt b/plotly/examples/src/main/kotlin/plots3d/surface3d.kt new file mode 100644 index 00000000..9871449f --- /dev/null +++ b/plotly/examples/src/main/kotlin/plots3d/surface3d.kt @@ -0,0 +1,35 @@ +package plots3d + +import space.kscience.dataforge.meta.asValue +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.TraceType +import space.kscience.plotly.trace + +private fun l(vararg numbers: Number) = numbers.map { it.asValue() }.asValue() + +fun main() { + val plot = Plotly.plot { + trace { + z.value = listOf( + l(8.83, 8.89, 8.81, 8.87, 8.9, 8.87), + l(8.89, 8.94, 8.85, 8.94, 8.96, 8.92), + l(8.84, 8.9, 8.82, 8.92, 8.93, 8.91), + l(8.79, 8.85, 8.79, 8.9, 8.94, 8.92), + l(8.79, 8.88, 8.81, 8.9, 8.95, 8.92), + l(8.8, 8.82, 8.78, 8.91, 8.94, 8.92), + l(8.75, 8.78, 8.77, 8.91, 8.95, 8.92), + l(8.8, 8.8, 8.77, 8.91, 8.95, 8.94), + l(8.74, 8.81, 8.76, 8.93, 8.98, 8.99), + l(8.89, 8.99, 8.92, 9.1, 9.13, 9.11), + l(8.97, 8.97, 8.91, 9.09, 9.11, 9.11), + l(9.04, 9.08, 9.05, 9.25, 9.28, 9.27), + l(9, 9.01, 9, 9.2, 9.23, 9.2), + l(8.99, 8.99, 8.98, 9.18, 9.2, 9.19), + l(8.93, 8.97, 8.97, 9.18, 9.2, 9.18) + ).asValue() + type = TraceType.surface + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/scatter/CategoricalDotPlot.kt b/plotly/examples/src/main/kotlin/scatter/CategoricalDotPlot.kt new file mode 100644 index 00000000..2e7be11d --- /dev/null +++ b/plotly/examples/src/main/kotlin/scatter/CategoricalDotPlot.kt @@ -0,0 +1,90 @@ +package scatter + +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.* + + +/** + * - Categorical dot scatter plot + * - Use different scatter modes + * - Choose marker's symbol and size + * - Change background plot color + */ +fun main() { + val country = listOf("Switzerland (2011)", "Chile (2013)", "Japan (2014)", "United States (2012)", + "Slovenia (2014)", "Canada (2011)", "Poland (2010)", "Estonia (2015)", "Luxembourg (2013)", "Portugal (2011)") + + val votingPop = listOf(40, 45.7, 52, 53.6, 54.1, 54.2, 54.5, 54.7, 55.1, 56.6) + + val regVoters = listOf(49.1, 42, 52.7, 84.3, 51.7, 61.1, 55.3, 64.2, 91.1, 58.9) + + val trace1 = Scatter { + x.numbers = votingPop + y.strings = country + mode = ScatterMode.markers + name = "Percent of estimated voting age population" + marker { + color("rgba(156, 165, 196, 0.95)") + line { + color("rgba(156, 165, 196, 1.0)") + width = 1 + } + symbol = Symbol.circle + size = 16 + } + } + + val trace2 = Scatter { + x.numbers = regVoters + y.strings = country + mode = ScatterMode.markers + name = "Percent of estimated registered voters" + marker { + color("rgba(204, 204, 204, 0.95)") + line { + color("rgba(217, 217, 217, 1.0)") + width = 1 + } + symbol = Symbol.circle + size = 16 + } + } + + val plot = Plotly.plot { + traces(trace1, trace2) + + layout { + title = "Votes cast for ten lowest voting age population in OECD countries" + xaxis { + showgrid = false + showline = true + linecolor("rgb(102, 102, 102)") + title { + font { color("rgb(204, 204, 204)") } + } + tickfont { color("rgb(102, 102, 102)") } + + autotick = false + dtick = Value.of(10) + ticks = Ticks.outside + tickcolor("rgb(102, 102, 102)") + } + + margin { l = 140; r = 40; b = 50; t = 80 } + legend { + font { size = 10 } + yanchor = YAnchor.middle + xanchor = XAnchor.right + } + width = 600 + height = 600 + paper_bgcolor("rgb(254, 247, 234)") + plot_bgcolor("rgb(254, 247, 234)") + hovermode = HoverMode.closest + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/scatter/DataLabelsOnThePlot.kt b/plotly/examples/src/main/kotlin/scatter/DataLabelsOnThePlot.kt new file mode 100644 index 00000000..60379e7b --- /dev/null +++ b/plotly/examples/src/main/kotlin/scatter/DataLabelsOnThePlot.kt @@ -0,0 +1,61 @@ +package scatter + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.ScatterMode +import space.kscience.plotly.models.TextPosition +import space.kscience.plotly.scatter + + +/** + * - Scatter plot only with markers + * - Data labels on the plot + * - Change textfont family + */ +fun main() { + val plot = Plotly.plot { + scatter { + x(1, 2, 3, 4) + y(10, 15, 13, 17) + mode = ScatterMode.markers + name = "Team A" + text("A-1", "A-2", "A-3", "A-4", "A-5") + textposition = TextPosition.`top center` + textfont { + family = "Raleway, sans-serif" + } + marker { size = 12 } + } + + scatter { + x(2, 3, 4, 5) + y(10, 15, 13, 17) + mode = ScatterMode.lines + name = "Team B" + text("B-a", "B-b", "B-c", "B-d", "B-e") + textposition = TextPosition.`bottom center` + textfont { + family = "Times New Roman" + } + marker { size = 12 } + } + + layout { + title = "Data Labels Hover" + xaxis { + range(0.75..5.25) + } + legend { + y = 0.5 + font { + family = "Arial, sans-serif" + size = 20 + color("grey") + } + } + } + } + + plot.makeFile() +} diff --git a/plotly/examples/src/main/kotlin/scatter/InterpolateOptions.kt b/plotly/examples/src/main/kotlin/scatter/InterpolateOptions.kt new file mode 100644 index 00000000..c31f4332 --- /dev/null +++ b/plotly/examples/src/main/kotlin/scatter/InterpolateOptions.kt @@ -0,0 +1,91 @@ +package scatter + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.LineShape +import space.kscience.plotly.models.Scatter +import space.kscience.plotly.models.ScatterMode +import space.kscience.plotly.models.TraceOrder + + +/** + * - Interpolate options + * - Legend styling + * - Choose scatter mode and line shapes + */ +fun main() { + val trace1 = Scatter { + x(1, 2, 3, 4, 5) + y(1, 3, 2, 3, 1) + mode = ScatterMode.`lines+markers` + name = "linear" + line { + shape = LineShape.linear + } + } + + val trace2 = Scatter { + x(1, 2, 3, 4, 5) + y(6, 8, 7, 8, 6) + mode = ScatterMode.`lines+markers` + name = "spline" + text("tweak line smoothness
with \"smoothing\" in line object") + line { + shape = LineShape.spline + } + } + + val trace3 = Scatter { + x(1, 2, 3, 4, 5) + y(11, 13, 12, 13, 11) + mode = ScatterMode.`lines+markers` + name = "vhv" + line { + shape = LineShape.vhv + } + } + + val trace4 = Scatter { + x(1, 2, 3, 4, 5) + y(16, 18, 17, 18, 16) + mode = ScatterMode.`lines+markers` + name = "hvh" + line { + shape = LineShape.hvh + } + } + + val trace5 = Scatter { + x(1, 2, 3, 4, 5) + y(21, 23, 22, 23, 21) + mode = ScatterMode.`lines+markers` + name = "vh" + line { + shape = LineShape.vh + } + } + + val trace6 = Scatter { + x(1, 2, 3, 4, 5) + y(26, 28, 27, 28, 26) + mode = ScatterMode.`lines+markers` + name = "hv" + line { + shape = LineShape.hv + } + } + + val plot = Plotly.plot { + traces(trace1, trace2, trace3, trace4, trace5, trace6) + + layout { + legend { + y = 0.5 + traceorder = TraceOrder.reversed + font { size = 16 } + } + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/scatter/LabellingLinesWithAnnotations.kt b/plotly/examples/src/main/kotlin/scatter/LabellingLinesWithAnnotations.kt new file mode 100644 index 00000000..76b3b99a --- /dev/null +++ b/plotly/examples/src/main/kotlin/scatter/LabellingLinesWithAnnotations.kt @@ -0,0 +1,162 @@ +package scatter + +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.* + + +/** + * - Styled scatter plot + * - Use array of traces + * - Style annotations + */ +fun main() { + val xData = listOf(2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013) + val yData = listOf( + listOf(74, 82, 80, 74, 73, 72, 74, 70, 70, 66, 66, 69), + listOf(45, 42, 50, 46, 36, 36, 34, 35, 32, 31, 31, 28), + listOf(13, 14, 20, 24, 20, 24, 24, 40, 35, 41, 43, 50), + listOf(18, 21, 18, 21, 16, 14, 13, 18, 17, 16, 19, 23)) + val colors = listOf("rgba(67, 67, 67, 1)", "rgba(115, 115, 115, 1)", + "rgba(49, 130, 189, 1)", "rgba(189, 189, 189, 1)") + val lineSize = listOf(2, 2, 4, 2) + val labels = listOf("Television", "Newspaper", "Internet", "Radio") + + val tracesList = mutableListOf() + for (i in yData.indices) { + val result = Scatter { + x.set(xData) + y.set(yData[i]) + line { + color(colors[i]) + width = lineSize[i] + } + } + tracesList.add(result) + + val result2 = Scatter { + x.set(listOf(xData[0], xData[11])) + y.set(listOf(yData[i][0], yData[i][11])) + mode = ScatterMode.markers + marker { + color(colors[i]) + size = 12 + } + } + tracesList.add(result2) + } + + val annotationsList = mutableListOf() + val text1 = Text { + xref = "paper" + yref = "paper" + x = Value.of(0.0) + y = Value.of(1.05) + xanchor = XAnchor.left + yanchor = YAnchor.bottom + text = "Main Source for News" + font { + family = "Arial" + size = 30 + color("rgb(37, 37, 37)") + } + showarrow = false + } + annotationsList.add(text1) + val text2 = Text { + xref = "paper" + yref = "paper" + x = Value.of(0.5) + y = Value.of(-0.1) + xanchor = XAnchor.center + yanchor = YAnchor.top + text = "Source: Pew Research Center & Storytelling with data" + showarrow = false + font { + family = "Arial" + size = 12 + color("rgb(150, 150, 150)") + } + } + annotationsList.add(text2) + for (i in yData.indices) { + val result = Text { + xref = "paper" + x = Value.of(0.05) + y = Value.of(yData[i][0]) + xanchor = XAnchor.right + yanchor = YAnchor.middle + text = labels[i] + " " + yData[i][0] + "%" + showarrow = false + font { + family = "Arial" + size = 16 + color("black") + } + } + annotationsList.add(result) + + val result2 = Text { + xref = "paper" + x = Value.of(0.95) + y = Value.of(yData[i][11]) + xanchor = XAnchor.left + yanchor = YAnchor.middle + text = yData[i][11].toString() + "%" + font { + family = "Arial" + size = 16 + color("black") + } + showarrow = false + } + annotationsList.add(result2) + } + + val plot = Plotly.plot { + traces(tracesList) + + layout { + showlegend = false + height = 600 + width = 600 + xaxis { + showline = true + showgrid = false + showticklabels = true + linecolor("rgb(204, 204, 204)") + linewidth = 2 + autotick = false + ticks = Ticks.outside + tickcolor("rgb(204, 204, 204)") + tickwidth = 2 + ticklen = 5 + tickfont { + family = "Arial" + size = 12 + color("rgb(82, 82, 82)") + } + } + + yaxis { + showgrid = false + zeroline = false + showline = false + showticklabels = false + } + + autosize = false + margin { + autoexpand = false + l = 100 + r = 20 + t = 100 + } + + annotations = annotationsList + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/scatter/LineAndScatterPlot.kt b/plotly/examples/src/main/kotlin/scatter/LineAndScatterPlot.kt new file mode 100644 index 00000000..ff3f6c1f --- /dev/null +++ b/plotly/examples/src/main/kotlin/scatter/LineAndScatterPlot.kt @@ -0,0 +1,38 @@ +package scatter + +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.ScatterMode +import space.kscience.plotly.scatter + + +/** + * - Scatter plot with different scatter modes (markers, lines, markers+lines) + */ +fun main() { + val plot = Plotly.plot { + scatter { + x(1, 2, 3, 4) + y(10, 15, 13, 17) + mode = ScatterMode.markers + } + + scatter { + x(2, 3, 4, 5) + y(10, 15, 13, 17) + mode = ScatterMode.lines + } + + scatter { + x(1, 2, 3, 4) + y(12, 5, 2, 12) + mode = ScatterMode.`lines+markers` + } + + layout { + title = "Line and Scatter Plot" + } + } + plot.makeFile() +} diff --git a/plotly/examples/src/main/kotlin/scatter/LogAxisScale.kt b/plotly/examples/src/main/kotlin/scatter/LogAxisScale.kt new file mode 100644 index 00000000..0b28f46f --- /dev/null +++ b/plotly/examples/src/main/kotlin/scatter/LogAxisScale.kt @@ -0,0 +1,40 @@ +package scatter + +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.Scatter + + +/** + * - Scatter plot with logarithmic axes + */ +fun main() { + val trace1 = Scatter { + x(0, 1, 2, 3, 4, 5, 6, 7, 8) + y(8, 7, 6, 5, 4, 3, 2, 1, 0) + } + + val trace2 = Scatter { + x(0, 1, 2, 3, 4, 5, 6, 7, 8) + y(0, 1, 2, 3, 4, 5, 6, 7, 8) + } + + val plot = Plotly.plot { + traces(trace1, trace2) + + layout { + title = "Log scale axis" + xaxis { + type = AxisType.log + autorange = true + } + yaxis { + type = AxisType.log + autorange = true + } + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/scatter/ScatterPlotWithColorDimension.kt b/plotly/examples/src/main/kotlin/scatter/ScatterPlotWithColorDimension.kt new file mode 100644 index 00000000..b353fd76 --- /dev/null +++ b/plotly/examples/src/main/kotlin/scatter/ScatterPlotWithColorDimension.kt @@ -0,0 +1,33 @@ +package scatter + +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.Scatter +import space.kscience.plotly.models.ScatterMode + + +/** + * - Scatter plot only with markers + * - Use numbers as color list + */ +fun main() { + val scatter = Scatter { + y.set(List(40) { 5.0 }) + mode = ScatterMode.markers + marker { + size = 40 + colors(List(40) { Value.of(it) }) + } + } + + val plot = Plotly.plot { + traces(scatter) + + layout { + title = "Scatter plot with color dimension" + } + } + plot.makeFile() +} diff --git a/plotly/examples/src/main/kotlin/scatter/VerticalAndHorizontalLines.kt b/plotly/examples/src/main/kotlin/scatter/VerticalAndHorizontalLines.kt new file mode 100644 index 00000000..91dfde0a --- /dev/null +++ b/plotly/examples/src/main/kotlin/scatter/VerticalAndHorizontalLines.kt @@ -0,0 +1,84 @@ +package scatter + +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.Dash +import space.kscience.plotly.models.Scatter +import space.kscience.plotly.models.ScatterMode +import space.kscience.plotly.models.ShapeType +import space.kscience.plotly.shape + + +/** + * - Text scatter mode + * - Add different lines using shapes + */ +fun main() { + val trace1 = Scatter { + x(2, 3.5, 6) + y(1, 1.5, 1) + text("Vertical Line", "Horizontal Dashed Line", "Diagonal dotted Line") + mode = ScatterMode.text + } + + val plot = Plotly.plot { + traces(trace1) + + layout { + title = "Vertical and Horizontal Lines Positioned Relative to the Axes" + xaxis { + range(0.0..7.0) + } + yaxis { + range(0.0..2.5) + } + + width = 700 + height = 500 + + // vertical line + shape { + type = ShapeType.line + x0 = Value.of(1) + y0 = Value.of(0) + x1 = Value.of(1) + y1 = Value.of(2) + line { + color("rgb(55, 128, 191") + width = 3 + } + } + + // horizontal line + shape { + type = ShapeType.line + x0 = Value.of(2) + y0 = Value.of(2) + x1 = Value.of(5) + y1 = Value.of(2) + line { + color("rgb(50, 171, 96)") + width = 4 + dash = Dash.dashdot + } + } + + // diagonal line + shape { + type = ShapeType.line + x0 = Value.of(4) + y0 = Value.of(0) + x1 = Value.of(6) + y1 = Value.of(2) + line { + color("rgb(128, 0, 128)") + width = 4 + dash = Dash.dot + } + } + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/scatter/stackedAreaPlot.kt b/plotly/examples/src/main/kotlin/scatter/stackedAreaPlot.kt new file mode 100644 index 00000000..86f22dec --- /dev/null +++ b/plotly/examples/src/main/kotlin/scatter/stackedAreaPlot.kt @@ -0,0 +1,38 @@ +package scatter + +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.GroupNorm +import space.kscience.plotly.models.ScatterMode +import space.kscience.plotly.scatter + + +/** + * from https://plotly.com/python/filled-area-plots/ + */ +fun main() { + val xValues = listOf("Winter", "Spring", "Summer", "Fall") + + Plotly.plot { + + fun stack(vararg ys: Number, colorOverride: String? = null) { + scatter { + x.strings = xValues + y(*ys) + hoverinfo = "x+y" + mode = ScatterMode.lines + line { + width = 0.5 + colorOverride?.let { color(colorOverride) } + } + stackgroup = "one" + groupnorm = GroupNorm.percent + } + } + + stack(40, 60, 40, 10, colorOverride = "rgb(131, 90, 241)") + stack(20, 10, 10, 60, colorOverride = "rgb(111, 231, 219)") + stack(40, 30, 50, 30, colorOverride = "rgb(184, 247, 212)") + + }.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/script/README.md b/plotly/examples/src/main/kotlin/script/README.md new file mode 100644 index 00000000..3d61bf8c --- /dev/null +++ b/plotly/examples/src/main/kotlin/script/README.md @@ -0,0 +1,3 @@ +# Run script + +`plotlykt-script customPage.plotly.kts` \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/script/customPage.plotly.kts b/plotly/examples/src/main/kotlin/script/customPage.plotly.kts new file mode 100644 index 00000000..2e91ec1f --- /dev/null +++ b/plotly/examples/src/main/kotlin/script/customPage.plotly.kts @@ -0,0 +1,29 @@ +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" } + + +plot { + 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" + } + } +} diff --git a/plotly/examples/src/main/kotlin/simpleServer.kt b/plotly/examples/src/main/kotlin/simpleServer.kt new file mode 100644 index 00000000..1ed21ca1 --- /dev/null +++ b/plotly/examples/src/main/kotlin/simpleServer.kt @@ -0,0 +1,90 @@ +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.html.a +import kotlinx.html.div +import kotlinx.html.h1 +import kotlinx.html.style +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plot +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.serve +import space.kscience.plotly.server.show +import kotlin.math.PI +import kotlin.math.cos +import kotlin.math.sin + +@ExperimentalCoroutinesApi +fun main() { + val server = Plotly.serve { + 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" } + + val plot1: Plot = Plotly.plot{ + traces(trace1, trace2) + layout { + title = "First graph, row: 1, size: 8/12" + xaxis { title = "x axis name" } + yaxis { title = "y axis name" } + } + } + + //root level plots go to default page + page { + h1 { +"This is the plot page" } + a("/other") { +"The other page" } + div { + style = "display: flex; align-items: stretch; " + div { + style = "width: 64%;" + plot(plot1) + } + div { + style = "width: 32%;" + plot { + traces(trace1, trace2) + layout { + title = "Second graph, row: 1, size: 4/12" + xaxis { title = "x axis name" } + yaxis { title = "y axis name" } + } + } + } + } + + + + div { + plot { + traces(trace1, trace2) + layout { + title = "Third graph, row: 2, size: 12/12" + xaxis { title = "x axis name" } + yaxis { title = "y axis name" } + } + } + } + } + + page("other") { + h1 { +"This is the other plot page" } + a("/") { +"Back to the main page" } + plot(plot1) + } + + } + + server.show() + + println("Press Enter to close server") + readLine() + + server.close() + +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/staticPlot.kt b/plotly/examples/src/main/kotlin/staticPlot.kt new file mode 100644 index 00000000..cac829d6 --- /dev/null +++ b/plotly/examples/src/main/kotlin/staticPlot.kt @@ -0,0 +1,31 @@ +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.trace +import kotlin.math.PI +import kotlin.math.sin + +fun main() { + val xValues = (0..100).map { it.toDouble() / 100.0 } + val yValues = xValues.map { sin(2.0 * PI * it) } + + val plot = Plotly.plot { + trace { + x.set(xValues) + y.set(yValues) + 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() +} diff --git a/plotly/examples/src/main/kotlin/svgSaveViaOrca.kt b/plotly/examples/src/main/kotlin/svgSaveViaOrca.kt new file mode 100644 index 00000000..50c7b123 --- /dev/null +++ b/plotly/examples/src/main/kotlin/svgSaveViaOrca.kt @@ -0,0 +1,88 @@ +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.UnstablePlotlyAPI +import space.kscience.plotly.export +import space.kscience.plotly.models.Scatter +import space.kscience.plotly.models.ScatterMode +import space.kscience.plotly.selectFile +import javax.swing.filechooser.FileNameExtensionFilter + + +/** + * - Scatter plot with many traces + * - Hide axis & grid lines + * - Export picture as svg using orca + */ +@OptIn(UnstablePlotlyAPI::class) +fun main() { + val trace1 = Scatter { + x(52698, 43117) + y(53, 31) + mode = ScatterMode.markers + name = "North America" + text("United States", "Canada") + marker { + color("rgb(164, 194, 244)") + size = 12 + line { + color("white") + width = 1 + } + } + } + + val trace2 = Scatter { + x(39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, 18007) + y(33, 20, 13, 19, 27, 19, 49, 44, 38) + mode = ScatterMode.markers + name = "Europe" + text("Germany", "Britain", "France", "Spain", "Italy", "Czech Rep.", "Greece", "Poland") + marker { + color("rgb(255, 217, 102)") + size = 12 + } + } + + val trace3 = Scatter { + x(42952, 37037, 33106, 17478, 9813, 5253, 4692, 3899) + y(23, 42, 54, 89, 14, 99, 93, 70) + mode = ScatterMode.markers + name = "Asia/Pacific" + text("Australia", "Japan", "South Korea", "Malaysia", "China", "Indonesia", "Philippines", "India") + marker { + color("rgb(234, 153, 153)") + size = 12 + } + } + + val trace4 = Scatter { + x(19097, 18601, 15595, 13546, 12026, 7434, 5419) + y(43, 47, 56, 80, 86, 93, 80) + mode = ScatterMode.markers + name = "Latin America" + text("Chile", "Argentina", "Mexico", "Venezuela", "Venezuela", "El Salvador", "Bolivia") + marker { + color("rgb(142, 124, 195)") + size = 12 + } + } + + val plot = Plotly.plot { + traces(trace1, trace2, trace3, trace4) + + layout { + title = "Quarter 1 Growth" + xaxis { + title = "GDP per Capita" + showgrid = false + zeroline = false + } + yaxis { + title = "Percent" + showline = false + } + } + } + + plot.export(selectFile(FileNameExtensionFilter("SVG","svg")) ?: error("File not selected")) +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/tabPageLayout.kt b/plotly/examples/src/main/kotlin/tabPageLayout.kt new file mode 100644 index 00000000..75cc6d9c --- /dev/null +++ b/plotly/examples/src/main/kotlin/tabPageLayout.kt @@ -0,0 +1,113 @@ +import kotlinx.html.* +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 + + +public class PlotTabs { + public data class Tab(val title: String, val id: String, val content: PlotlyFragment) + + private val _tabs = ArrayList() + public val tabs: List get() = _tabs + + public fun tab(title: String, id: String = title, block: FlowContent.(renderer: PlotlyRenderer) -> Unit) { + _tabs.add(Tab(title, id, PlotlyFragment(block))) + } +} + +public fun Plotly.tabs(tabsID: String = "tabs", block: PlotTabs.() -> Unit): PlotlyPage { + val grid = PlotTabs().apply(block) + + return page(cdnBootstrap, cdnPlotlyHeader) { container -> + ul("nav nav-tabs") { + role = "tablist" + id = tabsID + grid.tabs.forEachIndexed { index, tab -> + li("nav-item") { + a(classes = "nav-link") { + if (index == 0) { + classes = classes + "active" + } + id = "${tab.id}-tab" + attributes["data-toggle"] = "tab" + href = "#${tab.id}" + role = "tab" + attributes["aria-controls"] = tab.id + attributes["aria-selected"] = "true" + +tab.title + } + } + } + } + div("tab-content") { + id = "$tabsID-content" + grid.tabs.forEachIndexed { index, tab -> + div("tab-pane fade") { + if (index == 0) { + classes = classes + setOf("show", "active") + } + id = tab.id + role = "tabpanel" + attributes["aria-labelledby"] = "${tab.id}-tab" + tab.content.render(this, container) + } + } + } + } +} + + +@Suppress("DEPRECATION") +@UnstablePlotlyAPI +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 responsive = PlotlyConfig { + responsive = true + } + + val plot = Plotly.tabs { + + tab("First") { + plot(config = responsive) { + traces(trace1) + layout { + title = "First graph" + xaxis.title = "x axis name" + xaxis.title = "y axis name" + } + } + } + tab("Second") { + plot(config = responsive) { + traces(trace2) + layout { + title = "Second graph" + xaxis.title = "x axis name" + xaxis.title = "y axis name" + } + } + } + } + + plot.makeFile() +} diff --git a/plotly/examples/src/main/kotlin/table/BasicTable.kt b/plotly/examples/src/main/kotlin/table/BasicTable.kt new file mode 100644 index 00000000..0a49775f --- /dev/null +++ b/plotly/examples/src/main/kotlin/table/BasicTable.kt @@ -0,0 +1,63 @@ +package table + +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.HorizontalAlign +import space.kscience.plotly.models.Table + +/** + * - basic table trace with customization. + */ +fun main() { + val values = listOf( + listOf("Salaries", "Office", "Merchandise", "Legal", "TOTAL"), + listOf(1200000, 20000, 80000, 2000, 12120000), + listOf(1300000, 20000, 70000, 2000, 130902000), + listOf(1300000, 20000, 120000, 2000, 131222000), + listOf(1400000, 20000, 90000, 2000, 14102000), + ) + + val labels = listOf( + listOf("EXPENSES"), listOf("Q1"), listOf("Q2"), listOf("Q3"), listOf("Q4") + ) + + val table = Table { + columnorder(0, 1, 2, 4, 3) + columnwidth(10, 10, 30, 30, 20) + header { + this.values(labels) + align(HorizontalAlign.left, HorizontalAlign.center) + + line { + width = 1 + color("#506784") + } + fill { + color("#119DFF") + } + font { + family = "Arial" + size = 12 + color("white") + } + } + cells { + this.values(values) + align(HorizontalAlign.left, HorizontalAlign.center) + line { + width = 1 + color("#506784") + } + fill { + colors(listOf("#25FEFD", "white")) + } + font { + family = "Arial" + size = 11 + color("#506784") + } + } + } + + Plotly.plot { traces(table) }.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/tutorials/SinusPicture.kt b/plotly/examples/src/main/kotlin/tutorials/SinusPicture.kt new file mode 100644 index 00000000..2f951e8b --- /dev/null +++ b/plotly/examples/src/main/kotlin/tutorials/SinusPicture.kt @@ -0,0 +1,155 @@ +package tutorials + +import space.kscience.dataforge.meta.Value +import space.kscience.plotly.* +import space.kscience.plotly.models.* +import space.kscience.plotly.palettes.Xkcd +import kotlin.math.PI +import kotlin.math.sin + + +/** + * - Draw Math Graph with LaTeX annotations + * - Custom zeroline + * - Dashed and colored lines + * - Draw vertical lines + * - Use XKCD color palette + * - Change margins on the plot edges + * - Add shapes (vertical lines) + */ +fun main() { + val div = 200 / PI + val sub = PI / 6 + val xValues: List = (-410..410).map { it / div } + val yValues = mutableListOf() + val yText = mutableListOf() + + for (elem in xValues) { + val x = sin(elem) + yValues.add(x) + yText.add("sin = $x") + } + + val xElems = listOf(-2 * PI + sub, -PI - sub, sub, PI - sub) + val shapesList = xElems.map { elem -> + Shape { + xref = "x" + yref = "y" + startXY(elem, 0) + endXY(elem, 0.5) + line { color("red") } + } + } + + Plotly.page(mathJaxHeader, cdnPlotlyHeader) { + plot { + scatter { // sinus + x.set(xValues) + y.set(yValues) + name = "\$\\Large{y = \\mathrm{sin}\\,x}\$" + text.strings = yText + hoverinfo = "text" + line { color(Xkcd.CERULEAN) } + } + scatter { // sin(x) = 0 + mode = ScatterMode.markers + x(-2 * PI, -PI, PI, 2 * PI) + y(0, 0, 0, 0) + line { color(Xkcd.CERULEAN_BLUE) } + marker { size = 8 } + showlegend = false + hoverinfo = "none" + } + scatter { // sin(x) = 1/2 + mode = ScatterMode.markers + x.set(xElems + xElems) + y(0.5, 0.5, 0.5, 0.5, 0, 0, 0, 0) + line { color("red") } + marker { size = 8 } + showlegend = false + hoverinfo = "none" + } + scatter { + mode = ScatterMode.text + x(-0.35, 0.28, PI * 2 + 0.4) + y(0.56, 1.3, 0.1) + text.strings = listOf("\$\\Large{1/2}\$", "\$\\huge{y}\$", "\$\\huge{x}\$") + textfont { + colors(listOf("red", "black", "black")) + } + showlegend = false + hoverinfo = "none" + } + + layout { + height = 500 + width = 900 + shapes = shapesList + margin { l = 20; r = 20; b = 20; t = 50 } + + text { // arrow OX + y = Value.of(0) + x = Value.of(2 * PI + 20 / div) + ax = Value.of(-800) + ay = Value.of(0) + } + text { // arrow OY + x = Value.of(0) + y = Value.of(1 + 20 / div) + ax = Value.of(0) + ay = Value.of(430) + } + + shape { // y = 1 + xref = "x" + yref = "y" + startXY(-2 * PI, 1) + endXY(2 * PI, 1) + line { dash = Dash.dash } + } + shape { // y = 1/2 + xref = "x" + yref = "y" + startXY(-2 * PI, 0.5) + endXY(2 * PI, 0.5) + line { + color("red") + dash = Dash.dash + } + } + shape { // y = -1 + xref = "x" + yref = "y" + startXY(-2 * PI, -1) + endXY(2 * PI, -1) + line { dash = Dash.dash } + } + + xaxis { + zeroline = false + showgrid = false + anchor = "free" + position = 0.43 + 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}\$")) + } + yaxis { + zeroline = false + showgrid = false + anchor = "free" + position = 0.485 + tickvals(listOf(-0.91, 0.09, 1.09)) + ticktext(listOf("\$\\Large{-1}\$", "\$\\Large{0}\$", "\$\\Large{1}\$")) + } + legend { + x = 0.97 + y = 1 + borderwidth = 1 + font { size = 32 } + xanchor = XAnchor.right + yanchor = YAnchor.top + } + } + } + }.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/unsupportedFeature.kt b/plotly/examples/src/main/kotlin/unsupportedFeature.kt new file mode 100644 index 00000000..a8659da3 --- /dev/null +++ b/plotly/examples/src/main/kotlin/unsupportedFeature.kt @@ -0,0 +1,46 @@ +import space.kscience.dataforge.meta.ListValue +import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.asValue +import space.kscience.dataforge.meta.configure +import space.kscience.dataforge.meta.invoke +import space.kscience.dataforge.meta.set +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.Trace +import space.kscience.plotly.models.invoke + + +fun main() { + + val x = (0..5) + val y = x.map { it * it } + + val trace = Trace.invoke(x, y) { + name = "sin" + /* The hover text definition is currently not supported. + * We are applying it directly to configuration. + * It is still observable in the same way as other properties but is not type safe. + */ + meta["text"] = x.map { "label for $it".asValue() } + } + + val plot = Plotly.plot { + traces(trace) + layout { + title = "Plot with labels" + xaxis { + title = "x axis name" + configure { + "rangebreaks" putIndexed listOf( + Meta { + "values" put ListValue(2.0, 3.0) + } + ) + } + } + yaxis { title = "y axis name" } + } + } + + plot.makeFile() +} diff --git a/plotly/examples/src/main/kotlin/violin/AdvancedViolin.kt b/plotly/examples/src/main/kotlin/violin/AdvancedViolin.kt new file mode 100644 index 00000000..bd5fcfa1 --- /dev/null +++ b/plotly/examples/src/main/kotlin/violin/AdvancedViolin.kt @@ -0,0 +1,96 @@ +package violin + +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.* + + +/** + * - Styled violin plot + */ +fun main() { + val trace1 = Violin { + text("sample length: 32") + marker { + line { + width = 2 + color("#bebada") + } + symbol = Symbol.valueOf("line-ns") + } + orientation = Orientation.h + hoveron = ViolinHoveron.`points+kde` + meanline { + visible = true + } + legendgroup = "F" + scalegroup = "F" + points = ViolinPoints.all + pointpos = 1.2 + jitter = 0 + box { + visible = true + } + scalemode = ViolinScaleMode.count + showlegend = false + side = ViolinSide.positive + y0 = Value.of(0) + line { + color("#bebada") + } + name = "F" + + x(10.07, 34.83, 10.65, 12.43, 24.08, 13.42, 12.48, 29.8, 14.52, 11.38, + 20.27, 11.17, 12.26, 18.26, 8.51, 10.33, 14.15, 13.16, 17.47, 27.05, 16.43, + 8.35, 18.64, 11.87, 19.81, 43.11, 13.0, 12.74, 13.0, 16.4, 16.47, 18.78) + } + + val trace2 = Violin { + text("sample length: 32") + marker { + line { + width = 2 + color("#8dd3c7") + } + symbol = Symbol.valueOf("line-ns") + } + orientation = Orientation.h + hoveron = ViolinHoveron.`points+kde` + meanline { + visible = true + } + legendgroup = "M" + scalegroup = "M" + points = ViolinPoints.all + pointpos = -1.2 + jitter = 0 + box { + visible = true + } + scalemode = ViolinScaleMode.count + showlegend = false + side = ViolinSide.negative + y0 = Value.of(0) + + line { + color("#8dd3c7") + } + name = "M" + + x(27.2, 22.76, 17.29, 19.44, 16.66, 32.68, 15.98, 13.03, 18.28, 24.71, + 21.16, 11.69, 14.26, 15.95, 8.52, 22.82, 19.08, 16.0, 34.3, 41.19, 9.78, + 7.51, 28.44, 15.48, 16.58, 7.56, 10.34, 13.51, 18.71, 20.53) + } + + + val plot = Plotly.plot { + traces(trace1, trace2) + layout { + title = "Advanced Violin Plot" + } + } + + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/violin/BasicHorizontalViolinPlot.kt b/plotly/examples/src/main/kotlin/violin/BasicHorizontalViolinPlot.kt new file mode 100644 index 00000000..92b64cb1 --- /dev/null +++ b/plotly/examples/src/main/kotlin/violin/BasicHorizontalViolinPlot.kt @@ -0,0 +1,39 @@ +package violin + +import io.readResourceAsCsv +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.ViolinPoints +import space.kscience.plotly.violin + + +/** + * - Horizontal violin plot + * - Load resource from local file using krangl + * - Change colors of the plot + * - Show all points + */ +fun main() { + val df = readResourceAsCsv("/violin_data.csv") + + val plot = Plotly.plot { + violin { + x.set(df["total_bill"].values()) + points = ViolinPoints.all + box { visible = true } + line { color("black") } + fillcolor("#8dd3c7") + opacity = 0.6 + meanline { visible = true } + y0 = Value.of("Total Bill") + } + + layout { + title = "Basic Horizontal Violin Plot" + xaxis { zeroline = false } + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/violin/GroupedViolinPlot.kt b/plotly/examples/src/main/kotlin/violin/GroupedViolinPlot.kt new file mode 100644 index 00000000..25d8d6d7 --- /dev/null +++ b/plotly/examples/src/main/kotlin/violin/GroupedViolinPlot.kt @@ -0,0 +1,59 @@ +package violin + +import io.fromDataFrame +import io.readResourceAsCsv +import org.jetbrains.kotlinx.dataframe.api.column +import org.jetbrains.kotlinx.dataframe.api.filter +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.Violin +import space.kscience.plotly.models.ViolinMode + + +/** + * - Grouped violin plot + * - Load csv from local file using krangl + */ +fun main() { + val df = readResourceAsCsv("/violin_data.csv") + + val sex by column() + + val violin1 = Violin { + val males = df.filter { sex() == "Male" } + + x.fromDataFrame(males, "day") + y.fromDataFrame(males, "total_bill") + legendgroup = "M" + scalegroup = "M" + name = "M" + box { visible = true } + line { color("blue") } + meanline { visible = true } + } + + val violin2 = Violin { + val females = df.filter { sex() == "Female" } + + x.fromDataFrame(females, "day") + y.fromDataFrame(females, "total_bill") + legendgroup = "F" + scalegroup = "F" + name = "F" + box { visible = true } + line { color("pink") } + meanline { visible = true } + } + + val plot = Plotly.plot { + traces(violin1, violin2) + + layout { + title = "Grouped Violin Plot" + yaxis { zeroline = false } + violinmode = ViolinMode.group + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/violin/MultipleTracesViolin.kt b/plotly/examples/src/main/kotlin/violin/MultipleTracesViolin.kt new file mode 100644 index 00000000..37fe4db5 --- /dev/null +++ b/plotly/examples/src/main/kotlin/violin/MultipleTracesViolin.kt @@ -0,0 +1,76 @@ +package violin + +import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.api.column +import org.jetbrains.kotlinx.dataframe.api.filter +import org.jetbrains.kotlinx.dataframe.io.readCSV +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.violin + + +/** + * - Violin plot with multiple traces + * - Load resources from url using krangl + */ +fun main() { + val csvUrl = "https://raw.githubusercontent.com/plotly/datasets/master/violin_data.csv" + val df = DataFrame.readCSV(csvUrl) + + val day by column() + + val thursdayDf = df.filter { day() == "Thur" } + val fridayDf = df.filter { day() == "Fri" } + val saturdayDf = df.filter { day() == "Sat" } + val sundayDf = df.filter { day() == "Sun" } + + val plot = Plotly.plot { + violin { + name = "Thursday" + y.set(thursdayDf["total_bill"].values()) + + line { color("green") } + box { visible = true } + meanline { visible = true } + } + + violin { + name = "Friday" + y.set(fridayDf["total_bill"].values()) + + line { color("red") } + box { visible = true } + meanline { visible = true } + } + + violin { + name = "Saturday" + y.set(saturdayDf["total_bill"].values()) + + line { color("orange") } + box { visible = true } + meanline { visible = true } + } + + violin { + name = "Sunday" + y.set(sundayDf["total_bill"].values()) + + line { color("blue") } + box { visible = true } + meanline { visible = true } + } + + layout { + width = 700 + height = 450 + title = "Multiple Traces Violin Plot" + + yaxis { + zeroline = false + } + } + } + plot.makeFile() +} \ No newline at end of file diff --git a/plotly/examples/src/main/kotlin/worksheets/lineAndScatter.ws.kts b/plotly/examples/src/main/kotlin/worksheets/lineAndScatter.ws.kts new file mode 100644 index 00000000..a73a8b75 --- /dev/null +++ b/plotly/examples/src/main/kotlin/worksheets/lineAndScatter.ws.kts @@ -0,0 +1,29 @@ +import space.kscience.dataforge.meta.invoke +import space.kscience.plotly.Plotly +import space.kscience.plotly.models.ScatterMode +import space.kscience.plotly.scatter +import space.kscience.plotly.toHTML + +Plotly.plot { + scatter { + x(1, 2, 3, 4) + y(10, 15, 13, 17) + mode = ScatterMode.markers + } + + scatter { + x(2, 3, 4, 5) + y(10, 15, 13, 17) + mode = ScatterMode.lines + } + + scatter { + x(1, 2, 3, 4) + y(12, 5, 2, 12) + mode = ScatterMode.`lines+markers` + } + + layout { + title = "Line and Scatter Plot" + } +}.toHTML() \ No newline at end of file diff --git a/plotly/examples/src/main/resources/simpleData.txt b/plotly/examples/src/main/resources/simpleData.txt new file mode 100644 index 00000000..118dd534 --- /dev/null +++ b/plotly/examples/src/main/resources/simpleData.txt @@ -0,0 +1,2 @@ +1 2 3 4 +2 5 7 1 \ No newline at end of file diff --git a/plotly/examples/src/main/resources/violin_data.csv b/plotly/examples/src/main/resources/violin_data.csv new file mode 100644 index 00000000..402a92e0 --- /dev/null +++ b/plotly/examples/src/main/resources/violin_data.csv @@ -0,0 +1,245 @@ +total_bill,tip,sex,smoker,day,time,size +16.99,1.01,Female,No,Sun,Dinner,2 +10.34,1.66,Male,No,Sun,Dinner,3 +21.01,3.5,Male,No,Sun,Dinner,3 +23.68,3.31,Male,No,Sun,Dinner,2 +24.59,3.61,Female,No,Sun,Dinner,4 +25.29,4.71,Male,No,Sun,Dinner,4 +8.77,2,Male,No,Sun,Dinner,2 +26.88,3.12,Male,No,Sun,Dinner,4 +15.04,1.96,Male,No,Sun,Dinner,2 +14.78,3.23,Male,No,Sun,Dinner,2 +10.27,1.71,Male,No,Sun,Dinner,2 +35.26,5,Female,No,Sun,Dinner,4 +15.42,1.57,Male,No,Sun,Dinner,2 +18.43,3,Male,No,Sun,Dinner,4 +14.83,3.02,Female,No,Sun,Dinner,2 +21.58,3.92,Male,No,Sun,Dinner,2 +10.33,1.67,Female,No,Sun,Dinner,3 +16.29,3.71,Male,No,Sun,Dinner,3 +16.97,3.5,Female,No,Sun,Dinner,3 +20.65,3.35,Male,No,Sat,Dinner,3 +17.92,4.08,Male,No,Sat,Dinner,2 +20.29,2.75,Female,No,Sat,Dinner,2 +15.77,2.23,Female,No,Sat,Dinner,2 +39.42,7.58,Male,No,Sat,Dinner,4 +19.82,3.18,Male,No,Sat,Dinner,2 +17.81,2.34,Male,No,Sat,Dinner,4 +13.37,2,Male,No,Sat,Dinner,2 +12.69,2,Male,No,Sat,Dinner,2 +21.7,4.3,Male,No,Sat,Dinner,2 +19.65,3,Female,No,Sat,Dinner,2 +9.55,1.45,Male,No,Sat,Dinner,2 +18.35,2.5,Male,No,Sat,Dinner,4 +15.06,3,Female,No,Sat,Dinner,2 +20.69,2.45,Female,No,Sat,Dinner,4 +17.78,3.27,Male,No,Sat,Dinner,2 +24.06,3.6,Male,No,Sat,Dinner,3 +16.31,2,Male,No,Sat,Dinner,3 +16.93,3.07,Female,No,Sat,Dinner,3 +18.69,2.31,Male,No,Sat,Dinner,3 +31.27,5,Male,No,Sat,Dinner,3 +16.04,2.24,Male,No,Sat,Dinner,3 +17.46,2.54,Male,No,Sun,Dinner,2 +13.94,3.06,Male,No,Sun,Dinner,2 +9.68,1.32,Male,No,Sun,Dinner,2 +30.4,5.6,Male,No,Sun,Dinner,4 +18.29,3,Male,No,Sun,Dinner,2 +22.23,5,Male,No,Sun,Dinner,2 +32.4,6,Male,No,Sun,Dinner,4 +28.55,2.05,Male,No,Sun,Dinner,3 +18.04,3,Male,No,Sun,Dinner,2 +12.54,2.5,Male,No,Sun,Dinner,2 +10.29,2.6,Female,No,Sun,Dinner,2 +34.81,5.2,Female,No,Sun,Dinner,4 +9.94,1.56,Male,No,Sun,Dinner,2 +25.56,4.34,Male,No,Sun,Dinner,4 +19.49,3.51,Male,No,Sun,Dinner,2 +38.01,3,Male,Yes,Sat,Dinner,4 +26.41,1.5,Female,No,Sat,Dinner,2 +11.24,1.76,Male,Yes,Sat,Dinner,2 +48.27,6.73,Male,No,Sat,Dinner,4 +20.29,3.21,Male,Yes,Sat,Dinner,2 +13.81,2,Male,Yes,Sat,Dinner,2 +11.02,1.98,Male,Yes,Sat,Dinner,2 +18.29,3.76,Male,Yes,Sat,Dinner,4 +17.59,2.64,Male,No,Sat,Dinner,3 +20.08,3.15,Male,No,Sat,Dinner,3 +16.45,2.47,Female,No,Sat,Dinner,2 +3.07,1,Female,Yes,Sat,Dinner,1 +20.23,2.01,Male,No,Sat,Dinner,2 +15.01,2.09,Male,Yes,Sat,Dinner,2 +12.02,1.97,Male,No,Sat,Dinner,2 +17.07,3,Female,No,Sat,Dinner,3 +26.86,3.14,Female,Yes,Sat,Dinner,2 +25.28,5,Female,Yes,Sat,Dinner,2 +14.73,2.2,Female,No,Sat,Dinner,2 +10.51,1.25,Male,No,Sat,Dinner,2 +17.92,3.08,Male,Yes,Sat,Dinner,2 +27.2,4,Male,No,Thur,Lunch,4 +22.76,3,Male,No,Thur,Lunch,2 +17.29,2.71,Male,No,Thur,Lunch,2 +19.44,3,Male,Yes,Thur,Lunch,2 +16.66,3.4,Male,No,Thur,Lunch,2 +10.07,1.83,Female,No,Thur,Lunch,1 +32.68,5,Male,Yes,Thur,Lunch,2 +15.98,2.03,Male,No,Thur,Lunch,2 +34.83,5.17,Female,No,Thur,Lunch,4 +13.03,2,Male,No,Thur,Lunch,2 +18.28,4,Male,No,Thur,Lunch,2 +24.71,5.85,Male,No,Thur,Lunch,2 +21.16,3,Male,No,Thur,Lunch,2 +28.97,3,Male,Yes,Fri,Dinner,2 +22.49,3.5,Male,No,Fri,Dinner,2 +5.75,1,Female,Yes,Fri,Dinner,2 +16.32,4.3,Female,Yes,Fri,Dinner,2 +22.75,3.25,Female,No,Fri,Dinner,2 +40.17,4.73,Male,Yes,Fri,Dinner,4 +27.28,4,Male,Yes,Fri,Dinner,2 +12.03,1.5,Male,Yes,Fri,Dinner,2 +21.01,3,Male,Yes,Fri,Dinner,2 +12.46,1.5,Male,No,Fri,Dinner,2 +11.35,2.5,Female,Yes,Fri,Dinner,2 +15.38,3,Female,Yes,Fri,Dinner,2 +44.3,2.5,Female,Yes,Sat,Dinner,3 +22.42,3.48,Female,Yes,Sat,Dinner,2 +20.92,4.08,Female,No,Sat,Dinner,2 +15.36,1.64,Male,Yes,Sat,Dinner,2 +20.49,4.06,Male,Yes,Sat,Dinner,2 +25.21,4.29,Male,Yes,Sat,Dinner,2 +18.24,3.76,Male,No,Sat,Dinner,2 +14.31,4,Female,Yes,Sat,Dinner,2 +14,3,Male,No,Sat,Dinner,2 +7.25,1,Female,No,Sat,Dinner,1 +38.07,4,Male,No,Sun,Dinner,3 +23.95,2.55,Male,No,Sun,Dinner,2 +25.71,4,Female,No,Sun,Dinner,3 +17.31,3.5,Female,No,Sun,Dinner,2 +29.93,5.07,Male,No,Sun,Dinner,4 +10.65,1.5,Female,No,Thur,Lunch,2 +12.43,1.8,Female,No,Thur,Lunch,2 +24.08,2.92,Female,No,Thur,Lunch,4 +11.69,2.31,Male,No,Thur,Lunch,2 +13.42,1.68,Female,No,Thur,Lunch,2 +14.26,2.5,Male,No,Thur,Lunch,2 +15.95,2,Male,No,Thur,Lunch,2 +12.48,2.52,Female,No,Thur,Lunch,2 +29.8,4.2,Female,No,Thur,Lunch,6 +8.52,1.48,Male,No,Thur,Lunch,2 +14.52,2,Female,No,Thur,Lunch,2 +11.38,2,Female,No,Thur,Lunch,2 +22.82,2.18,Male,No,Thur,Lunch,3 +19.08,1.5,Male,No,Thur,Lunch,2 +20.27,2.83,Female,No,Thur,Lunch,2 +11.17,1.5,Female,No,Thur,Lunch,2 +12.26,2,Female,No,Thur,Lunch,2 +18.26,3.25,Female,No,Thur,Lunch,2 +8.51,1.25,Female,No,Thur,Lunch,2 +10.33,2,Female,No,Thur,Lunch,2 +14.15,2,Female,No,Thur,Lunch,2 +16,2,Male,Yes,Thur,Lunch,2 +13.16,2.75,Female,No,Thur,Lunch,2 +17.47,3.5,Female,No,Thur,Lunch,2 +34.3,6.7,Male,No,Thur,Lunch,6 +41.19,5,Male,No,Thur,Lunch,5 +27.05,5,Female,No,Thur,Lunch,6 +16.43,2.3,Female,No,Thur,Lunch,2 +8.35,1.5,Female,No,Thur,Lunch,2 +18.64,1.36,Female,No,Thur,Lunch,3 +11.87,1.63,Female,No,Thur,Lunch,2 +9.78,1.73,Male,No,Thur,Lunch,2 +7.51,2,Male,No,Thur,Lunch,2 +14.07,2.5,Male,No,Sun,Dinner,2 +13.13,2,Male,No,Sun,Dinner,2 +17.26,2.74,Male,No,Sun,Dinner,3 +24.55,2,Male,No,Sun,Dinner,4 +19.77,2,Male,No,Sun,Dinner,4 +29.85,5.14,Female,No,Sun,Dinner,5 +48.17,5,Male,No,Sun,Dinner,6 +25,3.75,Female,No,Sun,Dinner,4 +13.39,2.61,Female,No,Sun,Dinner,2 +16.49,2,Male,No,Sun,Dinner,4 +21.5,3.5,Male,No,Sun,Dinner,4 +12.66,2.5,Male,No,Sun,Dinner,2 +16.21,2,Female,No,Sun,Dinner,3 +13.81,2,Male,No,Sun,Dinner,2 +17.51,3,Female,Yes,Sun,Dinner,2 +24.52,3.48,Male,No,Sun,Dinner,3 +20.76,2.24,Male,No,Sun,Dinner,2 +31.71,4.5,Male,No,Sun,Dinner,4 +10.59,1.61,Female,Yes,Sat,Dinner,2 +10.63,2,Female,Yes,Sat,Dinner,2 +50.81,10,Male,Yes,Sat,Dinner,3 +15.81,3.16,Male,Yes,Sat,Dinner,2 +7.25,5.15,Male,Yes,Sun,Dinner,2 +31.85,3.18,Male,Yes,Sun,Dinner,2 +16.82,4,Male,Yes,Sun,Dinner,2 +32.9,3.11,Male,Yes,Sun,Dinner,2 +17.89,2,Male,Yes,Sun,Dinner,2 +14.48,2,Male,Yes,Sun,Dinner,2 +9.6,4,Female,Yes,Sun,Dinner,2 +34.63,3.55,Male,Yes,Sun,Dinner,2 +34.65,3.68,Male,Yes,Sun,Dinner,4 +23.33,5.65,Male,Yes,Sun,Dinner,2 +45.35,3.5,Male,Yes,Sun,Dinner,3 +23.17,6.5,Male,Yes,Sun,Dinner,4 +40.55,3,Male,Yes,Sun,Dinner,2 +20.69,5,Male,No,Sun,Dinner,5 +20.9,3.5,Female,Yes,Sun,Dinner,3 +30.46,2,Male,Yes,Sun,Dinner,5 +18.15,3.5,Female,Yes,Sun,Dinner,3 +23.1,4,Male,Yes,Sun,Dinner,3 +15.69,1.5,Male,Yes,Sun,Dinner,2 +19.81,4.19,Female,Yes,Thur,Lunch,2 +28.44,2.56,Male,Yes,Thur,Lunch,2 +15.48,2.02,Male,Yes,Thur,Lunch,2 +16.58,4,Male,Yes,Thur,Lunch,2 +7.56,1.44,Male,No,Thur,Lunch,2 +10.34,2,Male,Yes,Thur,Lunch,2 +43.11,5,Female,Yes,Thur,Lunch,4 +13,2,Female,Yes,Thur,Lunch,2 +13.51,2,Male,Yes,Thur,Lunch,2 +18.71,4,Male,Yes,Thur,Lunch,3 +12.74,2.01,Female,Yes,Thur,Lunch,2 +13,2,Female,Yes,Thur,Lunch,2 +16.4,2.5,Female,Yes,Thur,Lunch,2 +20.53,4,Male,Yes,Thur,Lunch,4 +16.47,3.23,Female,Yes,Thur,Lunch,3 +26.59,3.41,Male,Yes,Sat,Dinner,3 +38.73,3,Male,Yes,Sat,Dinner,4 +24.27,2.03,Male,Yes,Sat,Dinner,2 +12.76,2.23,Female,Yes,Sat,Dinner,2 +30.06,2,Male,Yes,Sat,Dinner,3 +25.89,5.16,Male,Yes,Sat,Dinner,4 +48.33,9,Male,No,Sat,Dinner,4 +13.27,2.5,Female,Yes,Sat,Dinner,2 +28.17,6.5,Female,Yes,Sat,Dinner,3 +12.9,1.1,Female,Yes,Sat,Dinner,2 +28.15,3,Male,Yes,Sat,Dinner,5 +11.59,1.5,Male,Yes,Sat,Dinner,2 +7.74,1.44,Male,Yes,Sat,Dinner,2 +30.14,3.09,Female,Yes,Sat,Dinner,4 +12.16,2.2,Male,Yes,Fri,Lunch,2 +13.42,3.48,Female,Yes,Fri,Lunch,2 +8.58,1.92,Male,Yes,Fri,Lunch,1 +15.98,3,Female,No,Fri,Lunch,3 +13.42,1.58,Male,Yes,Fri,Lunch,2 +16.27,2.5,Female,Yes,Fri,Lunch,2 +10.09,2,Female,Yes,Fri,Lunch,2 +20.45,3,Male,No,Sat,Dinner,4 +13.28,2.72,Male,No,Sat,Dinner,2 +22.12,2.88,Female,Yes,Sat,Dinner,2 +24.01,2,Male,Yes,Sat,Dinner,4 +15.69,3,Male,Yes,Sat,Dinner,3 +11.61,3.39,Male,No,Sat,Dinner,2 +10.77,1.47,Male,No,Sat,Dinner,2 +15.53,3,Male,Yes,Sat,Dinner,2 +10.07,1.25,Male,No,Sat,Dinner,2 +12.6,1,Male,Yes,Sat,Dinner,2 +32.83,1.17,Male,Yes,Sat,Dinner,2 +35.83,4.67,Female,No,Sat,Dinner,3 +29.03,5.92,Male,No,Sat,Dinner,3 +27.18,2,Female,Yes,Sat,Dinner,2 +22.67,2,Male,Yes,Sat,Dinner,2 +17.82,1.75,Male,No,Sat,Dinner,2 +18.78,3,Female,No,Thur,Dinner,2 diff --git a/plotly/plotlykt-core/README.md b/plotly/plotlykt-core/README.md new file mode 100644 index 00000000..da4cddad --- /dev/null +++ b/plotly/plotlykt-core/README.md @@ -0,0 +1,21 @@ +# Module plotlykt-core + + + +## Usage + +## Artifact: + +The Maven coordinates of this project are `space.kscience:plotlykt-core:0.7.1`. + +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:plotlykt-core:0.7.1") +} +``` diff --git a/plotly/plotlykt-core/api/plotlykt-core.api b/plotly/plotlykt-core/api/plotlykt-core.api new file mode 100644 index 00000000..c36b0b65 --- /dev/null +++ b/plotly/plotlykt-core/api/plotlykt-core.api @@ -0,0 +1,3183 @@ +public final class space/kscience/plotly/BootstrapHeadersKt { + public static final fun getCdnBootstrap ()Lspace/kscience/plotly/PlotlyHtmlFragment; +} + +public final class space/kscience/plotly/DfExtKt { + public static final fun numberGreaterThan (Lspace/kscience/dataforge/meta/Scheme;Ljava/lang/Number;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun numberGreaterThan$default (Lspace/kscience/dataforge/meta/Scheme;Ljava/lang/Number;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun numberInRange (Lspace/kscience/dataforge/meta/Scheme;Lkotlin/ranges/ClosedRange;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun numberInRange$default (Lspace/kscience/dataforge/meta/Scheme;Lkotlin/ranges/ClosedRange;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; +} + +public final class space/kscience/plotly/FileExportKt { + public static final fun display (Lspace/kscience/plotly/Plotly;Lkotlin/jvm/functions/Function2;)V + public static final fun export (Lspace/kscience/plotly/Plot;Ljava/nio/file/Path;Lspace/kscience/plotly/OrcaFormat;)V + public static synthetic fun export$default (Lspace/kscience/plotly/Plot;Ljava/nio/file/Path;Lspace/kscience/plotly/OrcaFormat;ILjava/lang/Object;)V + public static final fun makeFile (Lspace/kscience/plotly/Plot;Ljava/nio/file/Path;ZLspace/kscience/plotly/ResourceLocation;Lspace/kscience/plotly/PlotlyConfig;)V + public static final fun makeFile (Lspace/kscience/plotly/PlotlyFragment;Ljava/nio/file/Path;ZLjava/lang/String;Lspace/kscience/plotly/ResourceLocation;Ljava/util/List;)V + public static final fun makeFile (Lspace/kscience/plotly/PlotlyPage;Ljava/nio/file/Path;Z)V + public static synthetic fun makeFile$default (Lspace/kscience/plotly/Plot;Ljava/nio/file/Path;ZLspace/kscience/plotly/ResourceLocation;Lspace/kscience/plotly/PlotlyConfig;ILjava/lang/Object;)V + public static synthetic fun makeFile$default (Lspace/kscience/plotly/PlotlyFragment;Ljava/nio/file/Path;ZLjava/lang/String;Lspace/kscience/plotly/ResourceLocation;Ljava/util/List;ILjava/lang/Object;)V + public static synthetic fun makeFile$default (Lspace/kscience/plotly/PlotlyPage;Ljava/nio/file/Path;ZILjava/lang/Object;)V + public static final fun selectFile (Ljavax/swing/filechooser/FileNameExtensionFilter;)Ljava/nio/file/Path; + public static synthetic fun selectFile$default (Ljavax/swing/filechooser/FileNameExtensionFilter;ILjava/lang/Object;)Ljava/nio/file/Path; +} + +public final class space/kscience/plotly/HtmlKt { + public static final fun getCdnPlotlyHeader ()Lspace/kscience/plotly/PlotlyHtmlFragment; + public static final fun getMathJaxHeader ()Lspace/kscience/plotly/PlotlyHtmlFragment; + public static final fun plus (Lspace/kscience/plotly/PlotlyHtmlFragment;Lspace/kscience/plotly/PlotlyHtmlFragment;)Lspace/kscience/plotly/PlotlyHtmlFragment; + public static final fun toHTML (Lspace/kscience/plotly/Plot;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lspace/kscience/plotly/PlotlyConfig;)Ljava/lang/String; + public static synthetic fun toHTML$default (Lspace/kscience/plotly/Plot;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lspace/kscience/plotly/PlotlyConfig;ILjava/lang/Object;)Ljava/lang/String; +} + +public final class space/kscience/plotly/OrcaFormat : java/lang/Enum { + public static final field jpeg Lspace/kscience/plotly/OrcaFormat; + public static final field pdf Lspace/kscience/plotly/OrcaFormat; + public static final field png Lspace/kscience/plotly/OrcaFormat; + public static final field svg Lspace/kscience/plotly/OrcaFormat; + public static final field webp Lspace/kscience/plotly/OrcaFormat; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/OrcaFormat; + public static fun values ()[Lspace/kscience/plotly/OrcaFormat; +} + +public final class space/kscience/plotly/Plot : space/kscience/dataforge/meta/Configurable, space/kscience/dataforge/meta/MetaRepr, space/kscience/dataforge/meta/descriptors/Described { + public static final field Companion Lspace/kscience/plotly/Plot$Companion; + public fun ()V + public fun (Lspace/kscience/dataforge/meta/ObservableMutableMeta;)V + public synthetic fun (Lspace/kscience/dataforge/meta/ObservableMutableMeta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun addTrace (Lspace/kscience/plotly/models/Trace;)V + public final fun getData ()Ljava/util/List; + public fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public final fun getLayout ()Lspace/kscience/plotly/models/Layout; + public synthetic fun getMeta ()Lspace/kscience/dataforge/meta/MutableMeta; + public fun getMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public fun toMeta ()Lspace/kscience/dataforge/meta/Meta; + public final fun traces (Ljava/util/Collection;)V + public final fun traces ([Lspace/kscience/plotly/models/Trace;)V +} + +public final class space/kscience/plotly/Plot$Companion { + public final fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; +} + +public final class space/kscience/plotly/PlotExtensionsKt { + public static final fun bar (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Bar; + public static final fun box (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Box; + public static final fun candlestick (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/CandleStick; + public static final fun contour (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Contour; + public static final fun heatmap (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Heatmap; + public static final fun histogram (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Histogram; + public static final fun histogram2d (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Histogram2D; + public static final fun histogram2dcontour (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Histogram2DContour; + public static final fun pie (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Pie; + public static final fun scatter (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Scatter; + public static final fun shape (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)V + public static final fun table (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Table; + public static final fun text (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)V + public static final fun violin (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Violin; +} + +public final class space/kscience/plotly/PlotKt { + public static final fun Plot (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/plotly/Plot; + public static final fun layout (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)V + public static final fun toJsonString (Lspace/kscience/plotly/Plot;)Ljava/lang/String; + public static final fun trace (Lspace/kscience/plotly/Plot;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Trace; +} + +public final class space/kscience/plotly/Plotly { + public static final field INSTANCE Lspace/kscience/plotly/Plotly; + public static final field PLOTLY_CDN Ljava/lang/String; + public static final field VERSION Ljava/lang/String; + public final fun getCoordinateNames ()Ljava/util/List; + public final fun plot (Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/Plot; +} + +public final class space/kscience/plotly/PlotlyConfig : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/PlotlyConfig$Companion; + public fun ()V + public final fun getEditable ()Ljava/lang/Boolean; + public final fun getImageFormat ()Ljava/lang/String; + public final fun getPlotlyServerURL ()Ljava/lang/String; + public final fun getResponsive ()Ljava/lang/Boolean; + public final fun getShowEditInChartStudio ()Ljava/lang/Boolean; + public final fun saveAsSvg ()V + public final fun setEditable (Ljava/lang/Boolean;)V + public final fun setImageFormat (Ljava/lang/String;)V + public final fun setPlotlyServerURL (Ljava/lang/String;)V + public final fun setResponsive (Ljava/lang/Boolean;)V + public final fun setShowEditInChartStudio (Ljava/lang/Boolean;)V + public fun toString ()Ljava/lang/String; + public final fun withEditorButton ()V +} + +public final class space/kscience/plotly/PlotlyConfig$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/PlotlyFragment { + public fun (Lkotlin/jvm/functions/Function2;)V + public final fun getRender ()Lkotlin/jvm/functions/Function2; +} + +public final class space/kscience/plotly/PlotlyHeadersKt { + public static final fun localCssHeader (Ljava/nio/file/Path;Ljava/nio/file/Path;Ljava/lang/String;)Lspace/kscience/plotly/PlotlyHtmlFragment; + public static final fun localScriptHeader (Ljava/nio/file/Path;Ljava/nio/file/Path;Ljava/lang/String;)Lspace/kscience/plotly/PlotlyHtmlFragment; +} + +public final class space/kscience/plotly/PlotlyHtmlFragment { + public fun (Lkotlin/jvm/functions/Function1;)V + public final fun getVisit ()Lkotlin/jvm/functions/Function1; + public fun toString ()Ljava/lang/String; +} + +public final class space/kscience/plotly/PlotlyKt { + public static final fun toJsonString (Ljava/util/List;)Ljava/lang/String; + public static final fun toJsonString (Lspace/kscience/dataforge/meta/Scheme;)Ljava/lang/String; +} + +public final class space/kscience/plotly/PlotlyPage { + public fun (Ljava/util/Collection;Lspace/kscience/plotly/PlotlyFragment;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;)V + public synthetic fun (Ljava/util/Collection;Lspace/kscience/plotly/PlotlyFragment;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/util/Collection; + public final fun component2 ()Lspace/kscience/plotly/PlotlyFragment; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Lspace/kscience/plotly/PlotlyRenderer; + public final fun copy (Ljava/util/Collection;Lspace/kscience/plotly/PlotlyFragment;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;)Lspace/kscience/plotly/PlotlyPage; + public static synthetic fun copy$default (Lspace/kscience/plotly/PlotlyPage;Ljava/util/Collection;Lspace/kscience/plotly/PlotlyFragment;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;ILjava/lang/Object;)Lspace/kscience/plotly/PlotlyPage; + public fun equals (Ljava/lang/Object;)Z + public final fun getFragment ()Lspace/kscience/plotly/PlotlyFragment; + public final fun getHeaders ()Ljava/util/Collection; + public final fun getRenderer ()Lspace/kscience/plotly/PlotlyRenderer; + public final fun getTitle ()Ljava/lang/String; + public fun hashCode ()I + public final fun render ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; +} + +public final class space/kscience/plotly/PlotlyPageKt { + public static final fun fragment (Lspace/kscience/plotly/Plotly;Lkotlin/jvm/functions/Function2;)Lspace/kscience/plotly/PlotlyFragment; + public static final fun page (Lspace/kscience/plotly/Plotly;[Lspace/kscience/plotly/PlotlyHtmlFragment;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;Lkotlin/jvm/functions/Function2;)Lspace/kscience/plotly/PlotlyPage; + public static synthetic fun page$default (Lspace/kscience/plotly/Plotly;[Lspace/kscience/plotly/PlotlyHtmlFragment;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/plotly/PlotlyPage; + public static final fun toPage (Lspace/kscience/plotly/Plot;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lspace/kscience/plotly/PlotlyConfig;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;)Lspace/kscience/plotly/PlotlyPage; + public static final fun toPage (Lspace/kscience/plotly/PlotlyFragment;[Lspace/kscience/plotly/PlotlyHtmlFragment;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;)Lspace/kscience/plotly/PlotlyPage; + public static synthetic fun toPage$default (Lspace/kscience/plotly/Plot;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lspace/kscience/plotly/PlotlyConfig;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;ILjava/lang/Object;)Lspace/kscience/plotly/PlotlyPage; + public static synthetic fun toPage$default (Lspace/kscience/plotly/PlotlyFragment;[Lspace/kscience/plotly/PlotlyHtmlFragment;Ljava/lang/String;Lspace/kscience/plotly/PlotlyRenderer;ILjava/lang/Object;)Lspace/kscience/plotly/PlotlyPage; +} + +public abstract interface class space/kscience/plotly/PlotlyRenderer { + public abstract fun renderPlot (Lkotlinx/html/FlowContent;Lspace/kscience/plotly/Plot;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;)Lspace/kscience/plotly/Plot; + public static synthetic fun renderPlot$default (Lspace/kscience/plotly/PlotlyRenderer;Lkotlinx/html/FlowContent;Lspace/kscience/plotly/Plot;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;ILjava/lang/Object;)Lspace/kscience/plotly/Plot; +} + +public final class space/kscience/plotly/PlotlyRendererKt { + public static final fun plot (Lkotlinx/html/FlowContent;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;Lspace/kscience/plotly/PlotlyRenderer;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/Plot; + public static final fun plot (Lkotlinx/html/FlowContent;Lspace/kscience/plotly/Plot;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;Lspace/kscience/plotly/PlotlyRenderer;)Lspace/kscience/plotly/Plot; + public static synthetic fun plot$default (Lkotlinx/html/FlowContent;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;Lspace/kscience/plotly/PlotlyRenderer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/plotly/Plot; + public static synthetic fun plot$default (Lkotlinx/html/FlowContent;Lspace/kscience/plotly/Plot;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;Lspace/kscience/plotly/PlotlyRenderer;ILjava/lang/Object;)Lspace/kscience/plotly/Plot; +} + +public final class space/kscience/plotly/ResourceLocation : java/lang/Enum { + public static final field EMBED Lspace/kscience/plotly/ResourceLocation; + public static final field LOCAL Lspace/kscience/plotly/ResourceLocation; + public static final field REMOTE Lspace/kscience/plotly/ResourceLocation; + public static final field SYSTEM Lspace/kscience/plotly/ResourceLocation; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/ResourceLocation; + public static fun values ()[Lspace/kscience/plotly/ResourceLocation; +} + +public final class space/kscience/plotly/StaticPlotlyRenderer : space/kscience/plotly/PlotlyRenderer { + public static final field INSTANCE Lspace/kscience/plotly/StaticPlotlyRenderer; + public fun renderPlot (Lkotlinx/html/FlowContent;Lspace/kscience/plotly/Plot;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;)Lspace/kscience/plotly/Plot; +} + +public abstract interface annotation class space/kscience/plotly/UnstablePlotlyAPI : java/lang/annotation/Annotation { +} + +public abstract interface annotation class space/kscience/plotly/UnsupportedPlotlyAPI : java/lang/annotation/Annotation { +} + +public final class space/kscience/plotly/events/PlotlyEvent { + public fun (Ljava/util/List;)V + public final fun component1 ()Ljava/util/List; + public final fun copy (Ljava/util/List;)Lspace/kscience/plotly/events/PlotlyEvent; + public static synthetic fun copy$default (Lspace/kscience/plotly/events/PlotlyEvent;Ljava/util/List;ILjava/lang/Object;)Lspace/kscience/plotly/events/PlotlyEvent; + public fun equals (Ljava/lang/Object;)Z + public final fun getPoints ()Ljava/util/List; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class space/kscience/plotly/events/PlotlyEventListenerType : java/lang/Enum { + public static final field CLICK Lspace/kscience/plotly/events/PlotlyEventListenerType; + public static final field HOVER Lspace/kscience/plotly/events/PlotlyEventListenerType; + public static final field SELECTED Lspace/kscience/plotly/events/PlotlyEventListenerType; + public static final field SELECTING Lspace/kscience/plotly/events/PlotlyEventListenerType; + public static final field UNHOVER Lspace/kscience/plotly/events/PlotlyEventListenerType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public final fun getEventType ()Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/events/PlotlyEventListenerType; + public static fun values ()[Lspace/kscience/plotly/events/PlotlyEventListenerType; +} + +public final class space/kscience/plotly/events/PlotlyEventPoint { + public fun (ILkotlinx/serialization/json/JsonElement;Ljava/lang/Integer;Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/Value;)V + public synthetic fun (ILkotlinx/serialization/json/JsonElement;Ljava/lang/Integer;Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/Value;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()I + public final fun component2 ()Lkotlinx/serialization/json/JsonElement; + public final fun component3 ()Ljava/lang/Integer; + public final fun component4 ()Lspace/kscience/dataforge/meta/Value; + public final fun component5 ()Lspace/kscience/dataforge/meta/Value; + public final fun copy (ILkotlinx/serialization/json/JsonElement;Ljava/lang/Integer;Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/Value;)Lspace/kscience/plotly/events/PlotlyEventPoint; + public static synthetic fun copy$default (Lspace/kscience/plotly/events/PlotlyEventPoint;ILkotlinx/serialization/json/JsonElement;Ljava/lang/Integer;Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/Value;ILjava/lang/Object;)Lspace/kscience/plotly/events/PlotlyEventPoint; + public fun equals (Ljava/lang/Object;)Z + public final fun getCurveNumber ()I + public final fun getData ()Lkotlinx/serialization/json/JsonElement; + public final fun getPointNumber ()Ljava/lang/Integer; + public final fun getX ()Lspace/kscience/dataforge/meta/Value; + public final fun getY ()Lspace/kscience/dataforge/meta/Value; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class space/kscience/plotly/models/Axis : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Axis$Companion; + public fun ()V + public final fun getAnchor ()Ljava/lang/String; + public final fun getAutomargin ()Ljava/lang/Boolean; + public final fun getAutorange ()Z + public final fun getAutotick ()Ljava/lang/Boolean; + public final fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun getDtick ()Lspace/kscience/dataforge/meta/Value; + public final fun getGridcolor ()Lspace/kscience/plotly/models/Color; + public final fun getGridwidth ()Ljava/lang/Number; + public final fun getLinecolor ()Lspace/kscience/plotly/models/Color; + public final fun getLinewidth ()Ljava/lang/Number; + public final fun getOverlaying ()Ljava/lang/String; + public final fun getPosition ()Ljava/lang/Number; + public final fun getRange ()Lkotlin/ranges/ClosedFloatingPointRange; + public final fun getShowgrid ()Ljava/lang/Boolean; + public final fun getShowline ()Ljava/lang/Boolean; + public final fun getShowticklabels ()Ljava/lang/Boolean; + public final fun getSide ()Lspace/kscience/plotly/models/AxisSide; + public final fun getTickangle ()Ljava/lang/Number; + public final fun getTickcolor ()Lspace/kscience/plotly/models/Color; + public final fun getTickfont ()Lspace/kscience/plotly/models/Font; + public final fun getTicklen ()Ljava/lang/Number; + public final fun getTickmode ()Lspace/kscience/plotly/models/TickMode; + public final fun getTicks ()Lspace/kscience/plotly/models/Ticks; + public final fun getTicktext ()Ljava/util/List; + public final fun getTickvals ()Ljava/util/List; + public final fun getTickwidth ()Ljava/lang/Number; + public final fun getTitle ()Ljava/lang/String; + public final fun getType ()Lspace/kscience/plotly/models/AxisType; + public final fun getVisible ()Ljava/lang/Boolean; + public final fun getZeroline ()Ljava/lang/Boolean; + public final fun getZerolinecolor ()Lspace/kscience/plotly/models/Color; + public final fun getZerolinewidth ()Ljava/lang/Number; + public final fun range (Lkotlin/ranges/ClosedFloatingPointRange;)V + public final fun range (Lkotlin/ranges/ClosedRange;)V + public final fun range (Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/Value;)V + public final fun setAnchor (Ljava/lang/String;)V + public final fun setAutomargin (Ljava/lang/Boolean;)V + public final fun setAutorange (Z)V + public final fun setAutotick (Ljava/lang/Boolean;)V + public final fun setDtick (Lspace/kscience/dataforge/meta/Value;)V + public final fun setGridwidth (Ljava/lang/Number;)V + public final fun setLinewidth (Ljava/lang/Number;)V + public final fun setOverlaying (Ljava/lang/String;)V + public final fun setPosition (Ljava/lang/Number;)V + public final fun setRange (Lkotlin/ranges/ClosedFloatingPointRange;)V + public final fun setShowgrid (Ljava/lang/Boolean;)V + public final fun setShowline (Ljava/lang/Boolean;)V + public final fun setShowticklabels (Ljava/lang/Boolean;)V + public final fun setSide (Lspace/kscience/plotly/models/AxisSide;)V + public final fun setTickangle (Ljava/lang/Number;)V + public final fun setTickfont (Lspace/kscience/plotly/models/Font;)V + public final fun setTicklen (Ljava/lang/Number;)V + public final fun setTickmode (Lspace/kscience/plotly/models/TickMode;)V + public final fun setTicks (Lspace/kscience/plotly/models/Ticks;)V + public final fun setTicktext (Ljava/util/List;)V + public final fun setTickvals (Ljava/util/List;)V + public final fun setTickwidth (Ljava/lang/Number;)V + public final fun setTitle (Ljava/lang/String;)V + public final fun setType (Lspace/kscience/plotly/models/AxisType;)V + public final fun setVisible (Ljava/lang/Boolean;)V + public final fun setZeroline (Ljava/lang/Boolean;)V + public final fun setZerolinewidth (Ljava/lang/Number;)V + public final fun tickfont (Lkotlin/jvm/functions/Function1;)V + public final fun ticktext (Ljava/lang/Iterable;)V + public final fun tickvals (Ljava/lang/Iterable;)V + public final fun title (Lkotlin/jvm/functions/Function1;)V +} + +public final class space/kscience/plotly/models/Axis$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/AxisSide : java/lang/Enum { + public static final field bottom Lspace/kscience/plotly/models/AxisSide; + public static final field left Lspace/kscience/plotly/models/AxisSide; + public static final field right Lspace/kscience/plotly/models/AxisSide; + public static final field top Lspace/kscience/plotly/models/AxisSide; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/AxisSide; + public static fun values ()[Lspace/kscience/plotly/models/AxisSide; +} + +public final class space/kscience/plotly/models/AxisType : java/lang/Enum { + public static final field - Lspace/kscience/plotly/models/AxisType; + public static final field category Lspace/kscience/plotly/models/AxisType; + public static final field date Lspace/kscience/plotly/models/AxisType; + public static final field linear Lspace/kscience/plotly/models/AxisType; + public static final field log Lspace/kscience/plotly/models/AxisType; + public static final field multicategory Lspace/kscience/plotly/models/AxisType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/AxisType; + public static fun values ()[Lspace/kscience/plotly/models/AxisType; +} + +public final class space/kscience/plotly/models/Bar : space/kscience/plotly/models/Trace, space/kscience/plotly/models/SelectedPoints { + public static final field Companion Lspace/kscience/plotly/models/Bar$Companion; + public fun ()V + public final fun getBase ()Ljava/util/List; + public final fun getConstraintext ()Lspace/kscience/plotly/models/ConstrainText; + public final fun getOffset ()Ljava/lang/Number; + public final fun getOffsetsList ()Ljava/util/List; + public fun getSelected ()Lspace/kscience/plotly/models/SelectPoints; + public fun getSelectedpoints ()Ljava/util/List; + public fun getUnselected ()Lspace/kscience/plotly/models/SelectPoints; + public final fun getWidth ()Ljava/lang/Number; + public final fun getWidthList ()Ljava/util/List; + public final fun selected (Lkotlin/jvm/functions/Function1;)V + public final fun setBase (Ljava/util/List;)V + public final fun setConstraintext (Lspace/kscience/plotly/models/ConstrainText;)V + public final fun setOffset (Ljava/lang/Number;)V + public final fun setOffsetsList (Ljava/util/List;)V + public fun setSelected (Lspace/kscience/plotly/models/SelectPoints;)V + public fun setSelectedpoints (Ljava/util/List;)V + public fun setUnselected (Lspace/kscience/plotly/models/SelectPoints;)V + public final fun setWidth (Ljava/lang/Number;)V + public final fun setWidthList (Ljava/util/List;)V + public final fun unselected (Lkotlin/jvm/functions/Function1;)V +} + +public final class space/kscience/plotly/models/Bar$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/BarMode : java/lang/Enum { + public static final field group Lspace/kscience/plotly/models/BarMode; + public static final field overlay Lspace/kscience/plotly/models/BarMode; + public static final field relative Lspace/kscience/plotly/models/BarMode; + public static final field stack Lspace/kscience/plotly/models/BarMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/BarMode; + public static fun values ()[Lspace/kscience/plotly/models/BarMode; +} + +public final class space/kscience/plotly/models/BarNorm : java/lang/Enum { + public static final field "" Lspace/kscience/plotly/models/BarNorm; + public static final field fraction Lspace/kscience/plotly/models/BarNorm; + public static final field percent Lspace/kscience/plotly/models/BarNorm; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/BarNorm; + public static fun values ()[Lspace/kscience/plotly/models/BarNorm; +} + +public final class space/kscience/plotly/models/Bins : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Bins$Companion; + public fun ()V + public final fun getEnd ()Ljava/lang/Number; + public final fun getSize ()Ljava/lang/Number; + public final fun getStart ()Ljava/lang/Number; + public final fun setEnd (Ljava/lang/Number;)V + public final fun setSize (Ljava/lang/Number;)V + public final fun setStart (Ljava/lang/Number;)V +} + +public final class space/kscience/plotly/models/Bins$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/Box : space/kscience/plotly/models/Trace, space/kscience/plotly/models/SelectedPoints { + public static final field Companion Lspace/kscience/plotly/models/Box$Companion; + public fun ()V + public final fun getBoxmean ()Lspace/kscience/plotly/models/BoxMean; + public final fun getBoxpoints ()Lspace/kscience/plotly/models/BoxPoints; + public final fun getHoveron ()Lspace/kscience/plotly/models/BoxHoveron; + public final fun getJitter ()D + public final fun getLowerfence ()Ljava/util/List; + public final fun getMean ()Ljava/util/List; + public final fun getMedian ()Ljava/util/List; + public final fun getNotched ()Ljava/lang/Boolean; + public final fun getNotchspan ()Ljava/util/List; + public final fun getNotchwidth ()D + public final fun getPointpos ()D + public final fun getQ1 ()Ljava/util/List; + public final fun getQ3 ()Ljava/util/List; + public final fun getQuartilemethod ()Lspace/kscience/plotly/models/QuartileMethod; + public final fun getSd ()Ljava/util/List; + public fun getSelected ()Lspace/kscience/plotly/models/SelectPoints; + public fun getSelectedpoints ()Ljava/util/List; + public fun getUnselected ()Lspace/kscience/plotly/models/SelectPoints; + public final fun getUpperfence ()Ljava/util/List; + public final fun getWhiskerwidth ()D + public final fun getWidth ()Ljava/lang/Number; + public final fun lowerfence (Ljava/lang/Iterable;)V + public final fun mean (Ljava/lang/Iterable;)V + public final fun median (Ljava/lang/Iterable;)V + public final fun notchspan (Ljava/lang/Iterable;)V + public final fun q1 (Ljava/lang/Iterable;)V + public final fun q3 (Ljava/lang/Iterable;)V + public final fun sd (Ljava/lang/Iterable;)V + public final fun selected (Lkotlin/jvm/functions/Function1;)V + public final fun setBoxmean (Lspace/kscience/plotly/models/BoxMean;)V + public final fun setBoxpoints (Lspace/kscience/plotly/models/BoxPoints;)V + public final fun setHoveron (Lspace/kscience/plotly/models/BoxHoveron;)V + public final fun setJitter (D)V + public final fun setLowerfence (Ljava/util/List;)V + public final fun setMean (Ljava/util/List;)V + public final fun setMedian (Ljava/util/List;)V + public final fun setNotched (Ljava/lang/Boolean;)V + public final fun setNotchspan (Ljava/util/List;)V + public final fun setNotchwidth (D)V + public final fun setPointpos (D)V + public final fun setQ1 (Ljava/util/List;)V + public final fun setQ3 (Ljava/util/List;)V + public final fun setQuartilemethod (Lspace/kscience/plotly/models/QuartileMethod;)V + public final fun setSd (Ljava/util/List;)V + public fun setSelected (Lspace/kscience/plotly/models/SelectPoints;)V + public fun setSelectedpoints (Ljava/util/List;)V + public fun setUnselected (Lspace/kscience/plotly/models/SelectPoints;)V + public final fun setUpperfence (Ljava/util/List;)V + public final fun setWhiskerwidth (D)V + public final fun setWidth (Ljava/lang/Number;)V + public final fun unselected (Lkotlin/jvm/functions/Function1;)V + public final fun upperfence (Ljava/lang/Iterable;)V +} + +public final class space/kscience/plotly/models/Box$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/BoxHoveron : java/lang/Enum { + public static final field boxes Lspace/kscience/plotly/models/BoxHoveron; + public static final field boxes+points Lspace/kscience/plotly/models/BoxHoveron; + public static final field points Lspace/kscience/plotly/models/BoxHoveron; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/BoxHoveron; + public static fun values ()[Lspace/kscience/plotly/models/BoxHoveron; +} + +public final class space/kscience/plotly/models/BoxMean : java/lang/Enum { + public static final field false Lspace/kscience/plotly/models/BoxMean; + public static final field sd Lspace/kscience/plotly/models/BoxMean; + public static final field true Lspace/kscience/plotly/models/BoxMean; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/BoxMean; + public static fun values ()[Lspace/kscience/plotly/models/BoxMean; +} + +public final class space/kscience/plotly/models/BoxMode : java/lang/Enum { + public static final field group Lspace/kscience/plotly/models/BoxMode; + public static final field overlay Lspace/kscience/plotly/models/BoxMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/BoxMode; + public static fun values ()[Lspace/kscience/plotly/models/BoxMode; +} + +public final class space/kscience/plotly/models/BoxPoints : java/lang/Enum { + public static final field all Lspace/kscience/plotly/models/BoxPoints; + public static final field false Lspace/kscience/plotly/models/BoxPoints; + public static final field outliers Lspace/kscience/plotly/models/BoxPoints; + public static final field suspectedoutliers Lspace/kscience/plotly/models/BoxPoints; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/BoxPoints; + public static fun values ()[Lspace/kscience/plotly/models/BoxPoints; +} + +public final class space/kscience/plotly/models/Calendar : java/lang/Enum { + public static final field chinese Lspace/kscience/plotly/models/Calendar; + public static final field coptic Lspace/kscience/plotly/models/Calendar; + public static final field discworld Lspace/kscience/plotly/models/Calendar; + public static final field ethiopian Lspace/kscience/plotly/models/Calendar; + public static final field gregorian Lspace/kscience/plotly/models/Calendar; + public static final field hebrew Lspace/kscience/plotly/models/Calendar; + public static final field islamic Lspace/kscience/plotly/models/Calendar; + public static final field jalali Lspace/kscience/plotly/models/Calendar; + public static final field julian Lspace/kscience/plotly/models/Calendar; + public static final field mayan Lspace/kscience/plotly/models/Calendar; + public static final field nanakshahi Lspace/kscience/plotly/models/Calendar; + public static final field nepali Lspace/kscience/plotly/models/Calendar; + public static final field persian Lspace/kscience/plotly/models/Calendar; + public static final field taiwan Lspace/kscience/plotly/models/Calendar; + public static final field thai Lspace/kscience/plotly/models/Calendar; + public static final field ummalqura Lspace/kscience/plotly/models/Calendar; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/Calendar; + public static fun values ()[Lspace/kscience/plotly/models/Calendar; +} + +public final class space/kscience/plotly/models/CandleStick : space/kscience/plotly/models/Trace { + public static final field Companion Lspace/kscience/plotly/models/CandleStick$Companion; + public fun ()V + public final fun getCandleStickMeta ()Lspace/kscience/dataforge/meta/Value; + public final fun getClose ()Lspace/kscience/plotly/models/TraceValues; + public final fun getDecreasing ()Lspace/kscience/plotly/models/CandleStickLine; + public final fun getHigh ()Lspace/kscience/plotly/models/TraceValues; + public final fun getIds ()Ljava/util/List; + public final fun getIncreasing ()Lspace/kscience/plotly/models/CandleStickLine; + public final fun getLineWidth ()D + public final fun getLow ()Lspace/kscience/plotly/models/TraceValues; + public final fun getOpen ()Lspace/kscience/plotly/models/TraceValues; + public final fun getWhiskerwidth ()D + public final fun getXaxis ()Ljava/lang/String; + public final fun getXperiod ()Lspace/kscience/dataforge/meta/Value; + public final fun getXperiod0 ()Lspace/kscience/dataforge/meta/Value; + public final fun getXperiodalignment ()Lspace/kscience/plotly/models/XPeriodAlignment; + public final fun getYaxis ()Ljava/lang/String; + public final fun setCandleStickMeta (Lspace/kscience/dataforge/meta/Value;)V + public final fun setDecreasing (Lspace/kscience/plotly/models/CandleStickLine;)V + public final fun setIds (Ljava/util/List;)V + public final fun setIncreasing (Lspace/kscience/plotly/models/CandleStickLine;)V + public final fun setLineWidth (D)V + public final fun setWhiskerwidth (D)V + public final fun setXaxis (Ljava/lang/String;)V + public final fun setXperiod (Lspace/kscience/dataforge/meta/Value;)V + public final fun setXperiod0 (Lspace/kscience/dataforge/meta/Value;)V + public final fun setXperiodalignment (Lspace/kscience/plotly/models/XPeriodAlignment;)V + public final fun setYaxis (Ljava/lang/String;)V +} + +public final class space/kscience/plotly/models/CandleStick$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/CandleStickLine : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/CandleStickLine$Companion; + public fun ()V + public final fun getFillcolor ()Lspace/kscience/plotly/models/Color; + public final fun getLineColor ()Lspace/kscience/plotly/models/Color; + public final fun getLineWidth ()D + public final fun setLineWidth (D)V +} + +public final class space/kscience/plotly/models/CandleStickLine$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/Cells : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Cells$Companion; + public fun ()V + public final fun align (Ljava/util/List;)V + public final fun align (Lspace/kscience/plotly/models/HorizontalAlign;)V + public final fun align ([Lspace/kscience/plotly/models/HorizontalAlign;)V + public final fun fill (Lkotlin/jvm/functions/Function1;)V + public final fun font (Lkotlin/jvm/functions/Function1;)V + public final fun getAlign ()Lspace/kscience/plotly/models/TraceValues; + public final fun getFill ()Lspace/kscience/plotly/models/Fill; + public final fun getFont ()Lspace/kscience/plotly/models/Font; + public final fun getHeight ()Ljava/lang/Number; + public final fun getLine ()Lspace/kscience/plotly/models/LayoutLine; + public final fun getValues ()Lspace/kscience/plotly/models/TraceValues; + public final fun line (Lkotlin/jvm/functions/Function1;)V + public final fun setAlign (Lspace/kscience/plotly/models/TraceValues;)V + public final fun setFill (Lspace/kscience/plotly/models/Fill;)V + public final fun setFont (Lspace/kscience/plotly/models/Font;)V + public final fun setHeight (Ljava/lang/Number;)V + public final fun setLine (Lspace/kscience/plotly/models/LayoutLine;)V + public final fun setValues (Lspace/kscience/plotly/models/TraceValues;)V + public final fun values (Ljava/lang/Iterable;)V +} + +public final class space/kscience/plotly/models/Cells$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/Color { + public final fun getString ()Ljava/lang/String; + public final fun getValue ()Lspace/kscience/dataforge/meta/Value; + public final fun invoke (Ljava/lang/Number;)V + public final fun invoke (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V + public final fun invoke (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V + public final fun invoke (Ljava/lang/String;)V + public final fun setString (Ljava/lang/String;)V + public final fun setValue (Lspace/kscience/dataforge/meta/Value;)V +} + +public final class space/kscience/plotly/models/ColorBar : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/ColorBar$Companion; + public fun ()V + public final fun getBgcolor ()Lspace/kscience/plotly/models/Color; + public final fun getBordercolor ()Lspace/kscience/plotly/models/Color; + public final fun getBorderwidth ()Ljava/lang/Number; + public final fun getConstraintext ()Lspace/kscience/plotly/models/ConstrainText; + public final fun getLen ()Ljava/lang/Number; + public final fun getLenmode ()Lspace/kscience/plotly/models/MeasureMode; + public final fun getOutlinecolor ()Lspace/kscience/plotly/models/Color; + public final fun getOutlinewidth ()Ljava/lang/Number; + public final fun getThickness ()Ljava/lang/Number; + public final fun getThicknessmode ()Lspace/kscience/plotly/models/MeasureMode; + public final fun getTickfont ()Lspace/kscience/plotly/models/Font; + public final fun getTitle ()Lspace/kscience/plotly/models/Title; + public final fun getX ()Ljava/lang/Number; + public final fun getXanchor ()Lspace/kscience/plotly/models/XAnchor; + public final fun getXpad ()Ljava/lang/Number; + public final fun getY ()Ljava/lang/Number; + public final fun getYanchor ()Lspace/kscience/plotly/models/YAnchor; + public final fun getYpad ()I + public final fun setBorderwidth (Ljava/lang/Number;)V + public final fun setConstraintext (Lspace/kscience/plotly/models/ConstrainText;)V + public final fun setLen (Ljava/lang/Number;)V + public final fun setLenmode (Lspace/kscience/plotly/models/MeasureMode;)V + public final fun setOutlinewidth (Ljava/lang/Number;)V + public final fun setThickness (Ljava/lang/Number;)V + public final fun setThicknessmode (Lspace/kscience/plotly/models/MeasureMode;)V + public final fun setTickfont (Lspace/kscience/plotly/models/Font;)V + public final fun setTitle (Lspace/kscience/plotly/models/Title;)V + public final fun setX (Ljava/lang/Number;)V + public final fun setXanchor (Lspace/kscience/plotly/models/XAnchor;)V + public final fun setXpad (Ljava/lang/Number;)V + public final fun setY (Ljava/lang/Number;)V + public final fun setYanchor (Lspace/kscience/plotly/models/YAnchor;)V + public final fun setYpad (I)V + public final fun tickfont (Lkotlin/jvm/functions/Function1;)V + public final fun title (Lkotlin/jvm/functions/Function1;)V +} + +public final class space/kscience/plotly/models/ColorBar$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/ColorKt { + public static final fun color (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun color$default (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; +} + +public final class space/kscience/plotly/models/ConstrainText : java/lang/Enum { + public static final field both Lspace/kscience/plotly/models/ConstrainText; + public static final field inside Lspace/kscience/plotly/models/ConstrainText; + public static final field none Lspace/kscience/plotly/models/ConstrainText; + public static final field outside Lspace/kscience/plotly/models/ConstrainText; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ConstrainText; + public static fun values ()[Lspace/kscience/plotly/models/ConstrainText; +} + +public final class space/kscience/plotly/models/Contour : space/kscience/plotly/models/Trace, space/kscience/plotly/models/ContourSpec, space/kscience/plotly/models/HeatmapContour { + public static final field Companion Lspace/kscience/plotly/models/Contour$Companion; + public fun ()V + public final fun contours (Lkotlin/jvm/functions/Function1;)V + public fun getAutocontour ()Ljava/lang/Boolean; + public fun getContours ()Lspace/kscience/plotly/models/Contours; + public fun getNcontours ()I + public fun getXtype ()Lspace/kscience/plotly/models/DataType; + public fun getYtype ()Lspace/kscience/plotly/models/DataType; + public fun setAutocontour (Ljava/lang/Boolean;)V + public fun setContours (Lspace/kscience/plotly/models/Contours;)V + public fun setNcontours (I)V + public fun setXtype (Lspace/kscience/plotly/models/DataType;)V + public fun setYtype (Lspace/kscience/plotly/models/DataType;)V +} + +public final class space/kscience/plotly/models/Contour$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public abstract interface class space/kscience/plotly/models/ContourSpec { + public abstract fun getAutocontour ()Ljava/lang/Boolean; + public abstract fun getContours ()Lspace/kscience/plotly/models/Contours; + public abstract fun getNcontours ()I + public abstract fun setAutocontour (Ljava/lang/Boolean;)V + public abstract fun setContours (Lspace/kscience/plotly/models/Contours;)V + public abstract fun setNcontours (I)V +} + +public final class space/kscience/plotly/models/Contours : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Contours$Companion; + public fun ()V + public final fun getColoring ()Lspace/kscience/plotly/models/ContoursColoring; + public final fun getEnd ()Ljava/lang/Number; + public final fun getLabelfont ()Lspace/kscience/plotly/models/Font; + public final fun getShowlabels ()Ljava/lang/Boolean; + public final fun getShowlines ()Ljava/lang/Boolean; + public final fun getSize ()Ljava/lang/Number; + public final fun getStart ()Ljava/lang/Number; + public final fun getType ()Lspace/kscience/plotly/models/ContoursType; + public final fun labelfont (Lkotlin/jvm/functions/Function1;)V + public final fun setColoring (Lspace/kscience/plotly/models/ContoursColoring;)V + public final fun setEnd (Ljava/lang/Number;)V + public final fun setLabelfont (Lspace/kscience/plotly/models/Font;)V + public final fun setShowlabels (Ljava/lang/Boolean;)V + public final fun setShowlines (Ljava/lang/Boolean;)V + public final fun setSize (Ljava/lang/Number;)V + public final fun setStart (Ljava/lang/Number;)V + public final fun setType (Lspace/kscience/plotly/models/ContoursType;)V +} + +public final class space/kscience/plotly/models/Contours$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/ContoursColoring : java/lang/Enum { + public static final field fill Lspace/kscience/plotly/models/ContoursColoring; + public static final field heatmap Lspace/kscience/plotly/models/ContoursColoring; + public static final field lines Lspace/kscience/plotly/models/ContoursColoring; + public static final field none Lspace/kscience/plotly/models/ContoursColoring; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ContoursColoring; + public static fun values ()[Lspace/kscience/plotly/models/ContoursColoring; +} + +public final class space/kscience/plotly/models/ContoursType : java/lang/Enum { + public static final field constraint Lspace/kscience/plotly/models/ContoursType; + public static final field levels Lspace/kscience/plotly/models/ContoursType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ContoursType; + public static fun values ()[Lspace/kscience/plotly/models/ContoursType; +} + +public final class space/kscience/plotly/models/Cumulative : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Cumulative$Companion; + public fun ()V + public final fun getCurrentbin ()Lspace/kscience/plotly/models/CurrentBin; + public final fun getEnabled ()Ljava/lang/Boolean; + public final fun setCurrentbin (Lspace/kscience/plotly/models/CurrentBin;)V + public final fun setEnabled (Ljava/lang/Boolean;)V +} + +public final class space/kscience/plotly/models/Cumulative$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/CurrentBin : java/lang/Enum { + public static final field exclude Lspace/kscience/plotly/models/CurrentBin; + public static final field half Lspace/kscience/plotly/models/CurrentBin; + public static final field include Lspace/kscience/plotly/models/CurrentBin; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/CurrentBin; + public static fun values ()[Lspace/kscience/plotly/models/CurrentBin; +} + +public final class space/kscience/plotly/models/Dash : java/lang/Enum { + public static final field dash Lspace/kscience/plotly/models/Dash; + public static final field dashdot Lspace/kscience/plotly/models/Dash; + public static final field dot Lspace/kscience/plotly/models/Dash; + public static final field longdash Lspace/kscience/plotly/models/Dash; + public static final field longdashdot Lspace/kscience/plotly/models/Dash; + public static final field solid Lspace/kscience/plotly/models/Dash; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/Dash; + public static fun values ()[Lspace/kscience/plotly/models/Dash; +} + +public final class space/kscience/plotly/models/DataType : java/lang/Enum { + public static final field array Lspace/kscience/plotly/models/DataType; + public static final field scaled Lspace/kscience/plotly/models/DataType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/DataType; + public static fun values ()[Lspace/kscience/plotly/models/DataType; +} + +public final class space/kscience/plotly/models/Domain : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Domain$Companion; + public fun ()V + public final fun getColumn ()I + public final fun getRow ()I + public final fun getX ()Ljava/util/List; + public final fun getY ()Ljava/util/List; + public final fun setColumn (I)V + public final fun setRow (I)V + public final fun setX (Ljava/util/List;)V + public final fun setY (Ljava/util/List;)V +} + +public final class space/kscience/plotly/models/Domain$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/DragMode : java/lang/Enum { + public static final field drawcircle Lspace/kscience/plotly/models/DragMode; + public static final field drawclosedpath Lspace/kscience/plotly/models/DragMode; + public static final field drawline Lspace/kscience/plotly/models/DragMode; + public static final field drawopenpath Lspace/kscience/plotly/models/DragMode; + public static final field drawrect Lspace/kscience/plotly/models/DragMode; + public static final field false Lspace/kscience/plotly/models/DragMode; + public static final field lasso Lspace/kscience/plotly/models/DragMode; + public static final field orbit Lspace/kscience/plotly/models/DragMode; + public static final field pan Lspace/kscience/plotly/models/DragMode; + public static final field select Lspace/kscience/plotly/models/DragMode; + public static final field turntable Lspace/kscience/plotly/models/DragMode; + public static final field zoom Lspace/kscience/plotly/models/DragMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/DragMode; + public static fun values ()[Lspace/kscience/plotly/models/DragMode; +} + +public final class space/kscience/plotly/models/Error : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Error$Companion; + public fun ()V + public final fun getArray ()Ljava/util/List; + public final fun getArrayminus ()Ljava/util/List; + public final fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun getSymmetric ()Ljava/lang/Boolean; + public final fun getThickness ()Ljava/lang/Number; + public final fun getTraceref ()I + public final fun getTracerefminus ()I + public final fun getType ()Lspace/kscience/plotly/models/ErrorType; + public final fun getValue ()Ljava/lang/Number; + public final fun getValueminus ()Ljava/lang/Number; + public final fun getVisible ()Ljava/lang/Boolean; + public final fun getWidth ()Ljava/lang/Number; + public final fun setArray (Ljava/util/List;)V + public final fun setArrayminus (Ljava/util/List;)V + public final fun setSymmetric (Ljava/lang/Boolean;)V + public final fun setThickness (Ljava/lang/Number;)V + public final fun setTraceref (I)V + public final fun setTracerefminus (I)V + public final fun setType (Lspace/kscience/plotly/models/ErrorType;)V + public final fun setValue (Ljava/lang/Number;)V + public final fun setValueminus (Ljava/lang/Number;)V + public final fun setVisible (Ljava/lang/Boolean;)V + public final fun setWidth (Ljava/lang/Number;)V +} + +public final class space/kscience/plotly/models/Error$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/ErrorType : java/lang/Enum { + public static final field constant Lspace/kscience/plotly/models/ErrorType; + public static final field data Lspace/kscience/plotly/models/ErrorType; + public static final field percent Lspace/kscience/plotly/models/ErrorType; + public static final field sqrt Lspace/kscience/plotly/models/ErrorType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ErrorType; + public static fun values ()[Lspace/kscience/plotly/models/ErrorType; +} + +public final class space/kscience/plotly/models/Fill : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Fill$Companion; + public fun ()V + public final fun colors (Ljava/lang/Iterable;)V + public final fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun setColor (Lspace/kscience/plotly/models/Color;)V +} + +public final class space/kscience/plotly/models/Fill$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/FillTraceKt { + public static final fun appendXY (Lspace/kscience/plotly/models/Trace;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V + public static final fun appendXY (Lspace/kscience/plotly/models/Trace;[Lkotlin/Pair;)V + public static synthetic fun appendXY$default (Lspace/kscience/plotly/models/Trace;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILjava/lang/Object;)V + public static final fun functionXY (Lspace/kscience/plotly/models/Trace;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)V + public static final fun functionXY (Lspace/kscience/plotly/models/Trace;Lkotlin/ranges/ClosedFloatingPointRange;DLkotlin/jvm/functions/Function1;)V + public static final fun functionXY (Lspace/kscience/plotly/models/Trace;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function1;)V + public static synthetic fun functionXY$default (Lspace/kscience/plotly/models/Trace;Lkotlin/ranges/ClosedFloatingPointRange;DLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V +} + +public final class space/kscience/plotly/models/FillType : java/lang/Enum { + public static final field none Lspace/kscience/plotly/models/FillType; + public static final field tonext Lspace/kscience/plotly/models/FillType; + public static final field tonextx Lspace/kscience/plotly/models/FillType; + public static final field tonexty Lspace/kscience/plotly/models/FillType; + public static final field toself Lspace/kscience/plotly/models/FillType; + public static final field tozerox Lspace/kscience/plotly/models/FillType; + public static final field tozeroy Lspace/kscience/plotly/models/FillType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/FillType; + public static fun values ()[Lspace/kscience/plotly/models/FillType; +} + +public final class space/kscience/plotly/models/Font : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Font$Companion; + public fun ()V + public final fun colors (Ljava/lang/Iterable;)V + public final fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun getFamiliesList ()Ljava/util/List; + public final fun getFamily ()Ljava/lang/String; + public final fun getSize ()Ljava/lang/Number; + public final fun getSizesList ()Ljava/util/List; + public final fun setFamiliesList (Ljava/util/List;)V + public final fun setFamily (Ljava/lang/String;)V + public final fun setSize (Ljava/lang/Number;)V + public final fun setSizesList (Ljava/util/List;)V +} + +public final class space/kscience/plotly/models/Font$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/Gradient : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Gradient$Companion; + public fun ()V + public final fun colors (Ljava/lang/Iterable;)V + public final fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun getType ()Lspace/kscience/plotly/models/GradientType; + public final fun getTypesList ()Ljava/util/List; + public final fun setType (Lspace/kscience/plotly/models/GradientType;)V + public final fun setTypesList (Ljava/util/List;)V + public final fun typesList (Ljava/lang/Iterable;)V +} + +public final class space/kscience/plotly/models/Gradient$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/GradientType : java/lang/Enum { + public static final field horizontal Lspace/kscience/plotly/models/GradientType; + public static final field none Lspace/kscience/plotly/models/GradientType; + public static final field radial Lspace/kscience/plotly/models/GradientType; + public static final field vertical Lspace/kscience/plotly/models/GradientType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/GradientType; + public static fun values ()[Lspace/kscience/plotly/models/GradientType; +} + +public final class space/kscience/plotly/models/GroupNorm : java/lang/Enum { + public static final field Lspace/kscience/plotly/models/GroupNorm; + public static final field fraction Lspace/kscience/plotly/models/GroupNorm; + public static final field percent Lspace/kscience/plotly/models/GroupNorm; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/GroupNorm; + public static fun values ()[Lspace/kscience/plotly/models/GroupNorm; +} + +public final class space/kscience/plotly/models/Header : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Header$Companion; + public fun ()V + public final fun align (Ljava/util/List;)V + public final fun align (Lspace/kscience/plotly/models/HorizontalAlign;)V + public final fun align ([Lspace/kscience/plotly/models/HorizontalAlign;)V + public final fun fill (Lkotlin/jvm/functions/Function1;)V + public final fun font (Lkotlin/jvm/functions/Function1;)V + public final fun getAlign ()Lspace/kscience/plotly/models/TraceValues; + public final fun getFill ()Lspace/kscience/plotly/models/Fill; + public final fun getFont ()Lspace/kscience/plotly/models/Font; + public final fun getHeight ()Ljava/lang/Number; + public final fun getLine ()Lspace/kscience/plotly/models/LayoutLine; + public final fun getValues ()Lspace/kscience/plotly/models/TraceValues; + public final fun setAlign (Lspace/kscience/plotly/models/TraceValues;)V + public final fun setFill (Lspace/kscience/plotly/models/Fill;)V + public final fun setFont (Lspace/kscience/plotly/models/Font;)V + public final fun setHeight (Ljava/lang/Number;)V + public final fun setLine (Lspace/kscience/plotly/models/LayoutLine;)V + public final fun setValues (Lspace/kscience/plotly/models/TraceValues;)V + public final fun values (Ljava/lang/Iterable;)V +} + +public final class space/kscience/plotly/models/Header$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public class space/kscience/plotly/models/Heatmap : space/kscience/plotly/models/Trace, space/kscience/plotly/models/HeatmapContour, space/kscience/plotly/models/Table2D { + public static final field Companion Lspace/kscience/plotly/models/Heatmap$Companion; + public fun ()V + public fun getXgap ()Ljava/lang/Number; + public fun getXtype ()Lspace/kscience/plotly/models/DataType; + public fun getYgap ()Ljava/lang/Number; + public fun getYtype ()Lspace/kscience/plotly/models/DataType; + public fun getZsmooth ()Lspace/kscience/plotly/models/ZsmoothType; + public fun setXgap (Ljava/lang/Number;)V + public fun setXtype (Lspace/kscience/plotly/models/DataType;)V + public fun setYgap (Ljava/lang/Number;)V + public fun setYtype (Lspace/kscience/plotly/models/DataType;)V + public fun setZsmooth (Lspace/kscience/plotly/models/ZsmoothType;)V +} + +public final class space/kscience/plotly/models/Heatmap$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public abstract interface class space/kscience/plotly/models/HeatmapContour { + public abstract fun getXtype ()Lspace/kscience/plotly/models/DataType; + public abstract fun getYtype ()Lspace/kscience/plotly/models/DataType; + public abstract fun setXtype (Lspace/kscience/plotly/models/DataType;)V + public abstract fun setYtype (Lspace/kscience/plotly/models/DataType;)V +} + +public final class space/kscience/plotly/models/HeatmapGL : space/kscience/plotly/models/Heatmap { + public static final field Companion Lspace/kscience/plotly/models/HeatmapGL$Companion; + public fun ()V +} + +public final class space/kscience/plotly/models/HeatmapGL$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/HistFunc : java/lang/Enum { + public static final field average Lspace/kscience/plotly/models/HistFunc; + public static final field count Lspace/kscience/plotly/models/HistFunc; + public static final field max Lspace/kscience/plotly/models/HistFunc; + public static final field min Lspace/kscience/plotly/models/HistFunc; + public static final field sum Lspace/kscience/plotly/models/HistFunc; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/HistFunc; + public static fun values ()[Lspace/kscience/plotly/models/HistFunc; +} + +public final class space/kscience/plotly/models/HistNorm : java/lang/Enum { + public static final field density Lspace/kscience/plotly/models/HistNorm; + public static final field empty Lspace/kscience/plotly/models/HistNorm; + public static final field percent Lspace/kscience/plotly/models/HistNorm; + public static final field probability Lspace/kscience/plotly/models/HistNorm; + public static final field probability density Lspace/kscience/plotly/models/HistNorm; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/HistNorm; + public static fun values ()[Lspace/kscience/plotly/models/HistNorm; +} + +public class space/kscience/plotly/models/Histogram : space/kscience/plotly/models/Trace { + public static final field Companion Lspace/kscience/plotly/models/Histogram$Companion; + public fun ()V + public final fun cumulative (Lkotlin/jvm/functions/Function1;)V + public final fun getBingroup ()Ljava/lang/String; + public final fun getCumulative ()Lspace/kscience/plotly/models/Cumulative; + public final fun getDirection ()Lspace/kscience/plotly/models/HistogramDirection; + public final fun getHistfunc ()Lspace/kscience/plotly/models/HistFunc; + public final fun getHistnorm ()Lspace/kscience/plotly/models/HistNorm; + public final fun getNbinsx ()I + public final fun getNbinsy ()I + public final fun getXbingroup ()Ljava/lang/String; + public final fun getXbins ()Lspace/kscience/plotly/models/Bins; + public final fun getYbingroup ()Ljava/lang/String; + public final fun getYbins ()Lspace/kscience/plotly/models/Bins; + public final fun setBingroup (Ljava/lang/String;)V + public final fun setCumulative (Lspace/kscience/plotly/models/Cumulative;)V + public final fun setDirection (Lspace/kscience/plotly/models/HistogramDirection;)V + public final fun setHistfunc (Lspace/kscience/plotly/models/HistFunc;)V + public final fun setHistnorm (Lspace/kscience/plotly/models/HistNorm;)V + public final fun setNbinsx (I)V + public final fun setNbinsy (I)V + public final fun setXbingroup (Ljava/lang/String;)V + public final fun setXbins (Lspace/kscience/plotly/models/Bins;)V + public final fun setYbingroup (Ljava/lang/String;)V + public final fun setYbins (Lspace/kscience/plotly/models/Bins;)V + public final fun xbins (Lkotlin/jvm/functions/Function1;)V + public final fun ybins (Lkotlin/jvm/functions/Function1;)V +} + +public final class space/kscience/plotly/models/Histogram$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/Histogram2D : space/kscience/plotly/models/Histogram, space/kscience/plotly/models/Table2D { + public static final field Companion Lspace/kscience/plotly/models/Histogram2D$Companion; + public fun ()V + public fun getXgap ()Ljava/lang/Number; + public fun getYgap ()Ljava/lang/Number; + public fun getZsmooth ()Lspace/kscience/plotly/models/ZsmoothType; + public fun setXgap (Ljava/lang/Number;)V + public fun setYgap (Ljava/lang/Number;)V + public fun setZsmooth (Lspace/kscience/plotly/models/ZsmoothType;)V +} + +public final class space/kscience/plotly/models/Histogram2D$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/Histogram2DContour : space/kscience/plotly/models/Histogram, space/kscience/plotly/models/ContourSpec { + public static final field Companion Lspace/kscience/plotly/models/Histogram2DContour$Companion; + public fun ()V + public final fun contours (Lkotlin/jvm/functions/Function1;)V + public fun getAutocontour ()Ljava/lang/Boolean; + public fun getContours ()Lspace/kscience/plotly/models/Contours; + public fun getNcontours ()I + public fun setAutocontour (Ljava/lang/Boolean;)V + public fun setContours (Lspace/kscience/plotly/models/Contours;)V + public fun setNcontours (I)V +} + +public final class space/kscience/plotly/models/Histogram2DContour$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/HistogramDirection : java/lang/Enum { + public static final field decreasing Lspace/kscience/plotly/models/HistogramDirection; + public static final field increasing Lspace/kscience/plotly/models/HistogramDirection; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/HistogramDirection; + public static fun values ()[Lspace/kscience/plotly/models/HistogramDirection; +} + +public final class space/kscience/plotly/models/HorizontalAlign : java/lang/Enum { + public static final field center Lspace/kscience/plotly/models/HorizontalAlign; + public static final field left Lspace/kscience/plotly/models/HorizontalAlign; + public static final field right Lspace/kscience/plotly/models/HorizontalAlign; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/HorizontalAlign; + public static fun values ()[Lspace/kscience/plotly/models/HorizontalAlign; +} + +public final class space/kscience/plotly/models/HoverMode : java/lang/Enum { + public static final field closest Lspace/kscience/plotly/models/HoverMode; + public static final field false Lspace/kscience/plotly/models/HoverMode; + public static final field x Lspace/kscience/plotly/models/HoverMode; + public static final field x unified Lspace/kscience/plotly/models/HoverMode; + public static final field y Lspace/kscience/plotly/models/HoverMode; + public static final field y unified Lspace/kscience/plotly/models/HoverMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/HoverMode; + public static fun values ()[Lspace/kscience/plotly/models/HoverMode; +} + +public final class space/kscience/plotly/models/Hoverlabel : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Hoverlabel$Companion; + public fun ()V + public final fun align (Ljava/util/List;)V + public final fun align (Lspace/kscience/plotly/models/HorizontalAlign;)V + public final fun align ([Lspace/kscience/plotly/models/HorizontalAlign;)V + public final fun bgcolors (Ljava/lang/Iterable;)V + public final fun bordercolors (Ljava/lang/Iterable;)V + public final fun font (Lkotlin/jvm/functions/Function1;)V + public final fun getAlign ()Lspace/kscience/plotly/models/TraceValues; + public final fun getBgcolor ()Lspace/kscience/plotly/models/Color; + public final fun getBordercolor ()Lspace/kscience/plotly/models/Color; + public final fun getFont ()Lspace/kscience/plotly/models/Font; + public final fun getNamelength ()Ljava/lang/Number; + public final fun getNamelengths ()Ljava/util/List; + public final fun setAlign (Lspace/kscience/plotly/models/TraceValues;)V + public final fun setBgcolor (Lspace/kscience/plotly/models/Color;)V + public final fun setBordercolor (Lspace/kscience/plotly/models/Color;)V + public final fun setFont (Lspace/kscience/plotly/models/Font;)V + public final fun setNamelength (Ljava/lang/Number;)V + public final fun setNamelengths (Ljava/util/List;)V +} + +public final class space/kscience/plotly/models/Hoverlabel$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/Image : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Image$Companion; + public fun ()V + public final fun getLayer ()Lspace/kscience/plotly/models/ImageLayer; + public final fun getName ()Ljava/lang/String; + public final fun getOpacity ()D + public final fun getSizex ()D + public final fun getSizey ()D + public final fun getSizing ()Lspace/kscience/plotly/models/ImageSizing; + public final fun getSource ()Ljava/lang/String; + public final fun getTemplateitemname ()Ljava/lang/String; + public final fun getVisible ()Z + public final fun getX ()D + public final fun getXanchor ()Lspace/kscience/plotly/models/ImageXAnchor; + public final fun getXref ()Ljava/lang/String; + public final fun getY ()D + public final fun getYanchor ()Lspace/kscience/plotly/models/ImageYAnchor; + public final fun getYref ()Ljava/lang/String; + public final fun setLayer (Lspace/kscience/plotly/models/ImageLayer;)V + public final fun setName (Ljava/lang/String;)V + public final fun setOpacity (D)V + public final fun setSizex (D)V + public final fun setSizey (D)V + public final fun setSizing (Lspace/kscience/plotly/models/ImageSizing;)V + public final fun setSource (Ljava/lang/String;)V + public final fun setTemplateitemname (Ljava/lang/String;)V + public final fun setVisible (Z)V + public final fun setX (D)V + public final fun setXanchor (Lspace/kscience/plotly/models/ImageXAnchor;)V + public final fun setXref (Ljava/lang/String;)V + public final fun setY (D)V + public final fun setYanchor (Lspace/kscience/plotly/models/ImageYAnchor;)V + public final fun setYref (Ljava/lang/String;)V +} + +public final class space/kscience/plotly/models/Image$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/ImageLayer : java/lang/Enum { + public static final field above Lspace/kscience/plotly/models/ImageLayer; + public static final field below Lspace/kscience/plotly/models/ImageLayer; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ImageLayer; + public static fun values ()[Lspace/kscience/plotly/models/ImageLayer; +} + +public final class space/kscience/plotly/models/ImageSizing : java/lang/Enum { + public static final field contain Lspace/kscience/plotly/models/ImageSizing; + public static final field fill Lspace/kscience/plotly/models/ImageSizing; + public static final field stretch Lspace/kscience/plotly/models/ImageSizing; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ImageSizing; + public static fun values ()[Lspace/kscience/plotly/models/ImageSizing; +} + +public final class space/kscience/plotly/models/ImageXAnchor : java/lang/Enum { + public static final field center Lspace/kscience/plotly/models/ImageXAnchor; + public static final field left Lspace/kscience/plotly/models/ImageXAnchor; + public static final field right Lspace/kscience/plotly/models/ImageXAnchor; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ImageXAnchor; + public static fun values ()[Lspace/kscience/plotly/models/ImageXAnchor; +} + +public final class space/kscience/plotly/models/ImageYAnchor : java/lang/Enum { + public static final field bottom Lspace/kscience/plotly/models/ImageYAnchor; + public static final field middle Lspace/kscience/plotly/models/ImageYAnchor; + public static final field top Lspace/kscience/plotly/models/ImageYAnchor; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ImageYAnchor; + public static fun values ()[Lspace/kscience/plotly/models/ImageYAnchor; +} + +public final class space/kscience/plotly/models/Layout : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Layout$Companion; + public fun ()V + public final fun annotation (Lkotlin/jvm/functions/Function1;)V + public final fun annotation (Lspace/kscience/plotly/models/Text;)V + public final fun figure (Lkotlin/jvm/functions/Function1;)V + public final fun figure (Lspace/kscience/plotly/models/Shape;)V + public final fun getAnnotations ()Ljava/util/List; + public final fun getAutosize ()Ljava/lang/Boolean; + public final fun getBargap ()Ljava/lang/Number; + public final fun getBargroupgap ()Ljava/lang/Number; + public final fun getBarmode ()Lspace/kscience/plotly/models/BarMode; + public final fun getBarnorm ()Lspace/kscience/plotly/models/BarNorm; + public final fun getBoxgap ()Ljava/lang/Number; + public final fun getBoxgroupgap ()Ljava/lang/Number; + public final fun getBoxmode ()Lspace/kscience/plotly/models/BoxMode; + public final fun getCalendar ()Lspace/kscience/plotly/models/Calendar; + public final fun getDragmode ()Lspace/kscience/plotly/models/DragMode; + public final fun getHeight ()Ljava/lang/Number; + public final fun getHoverdistance ()Ljava/lang/Number; + public final fun getHovermode ()Lspace/kscience/plotly/models/HoverMode; + public final fun getLegend ()Lspace/kscience/plotly/models/Legend; + public final fun getMargin ()Lspace/kscience/plotly/models/Margin; + public final fun getPaper_bgcolor ()Lspace/kscience/plotly/models/Color; + public final fun getPlot_bgcolor ()Lspace/kscience/plotly/models/Color; + public final fun getSeparators ()Ljava/lang/String; + public final fun getShapes ()Ljava/util/List; + public final fun getShowlegend ()Ljava/lang/Boolean; + public final fun getTitle ()Ljava/lang/String; + public final fun getViolingap ()Ljava/lang/Number; + public final fun getViolingroupgap ()Ljava/lang/Number; + public final fun getViolinmode ()Lspace/kscience/plotly/models/ViolinMode; + public final fun getWidth ()Ljava/lang/Number; + public final fun getXaxis ()Lspace/kscience/plotly/models/Axis; + public final fun getYaxis ()Lspace/kscience/plotly/models/Axis; + public final fun image (Lkotlin/jvm/functions/Function1;)V + public final fun image (Lspace/kscience/plotly/models/Image;)V + public final fun legend (Lkotlin/jvm/functions/Function1;)V + public final fun margin (Lkotlin/jvm/functions/Function1;)V + public final fun setAnnotations (Ljava/util/List;)V + public final fun setAutosize (Ljava/lang/Boolean;)V + public final fun setBargap (Ljava/lang/Number;)V + public final fun setBargroupgap (Ljava/lang/Number;)V + public final fun setBarmode (Lspace/kscience/plotly/models/BarMode;)V + public final fun setBarnorm (Lspace/kscience/plotly/models/BarNorm;)V + public final fun setBoxgap (Ljava/lang/Number;)V + public final fun setBoxgroupgap (Ljava/lang/Number;)V + public final fun setBoxmode (Lspace/kscience/plotly/models/BoxMode;)V + public final fun setCalendar (Lspace/kscience/plotly/models/Calendar;)V + public final fun setDragmode (Lspace/kscience/plotly/models/DragMode;)V + public final fun setHeight (Ljava/lang/Number;)V + public final fun setHoverdistance (Ljava/lang/Number;)V + public final fun setHovermode (Lspace/kscience/plotly/models/HoverMode;)V + public final fun setLegend (Lspace/kscience/plotly/models/Legend;)V + public final fun setMargin (Lspace/kscience/plotly/models/Margin;)V + public final fun setSeparators (Ljava/lang/String;)V + public final fun setShapes (Ljava/util/List;)V + public final fun setShowlegend (Ljava/lang/Boolean;)V + public final fun setTitle (Ljava/lang/String;)V + public final fun setViolingap (Ljava/lang/Number;)V + public final fun setViolingroupgap (Ljava/lang/Number;)V + public final fun setViolinmode (Lspace/kscience/plotly/models/ViolinMode;)V + public final fun setWidth (Ljava/lang/Number;)V + public final fun setXaxis (Lspace/kscience/plotly/models/Axis;)V + public final fun setYaxis (Lspace/kscience/plotly/models/Axis;)V + public final fun title (Lkotlin/jvm/functions/Function1;)V + public final fun xaxis (Lkotlin/jvm/functions/Function1;)V + public final fun yaxis (ILkotlin/jvm/functions/Function1;)V + public final fun yaxis (Lkotlin/jvm/functions/Function1;)V +} + +public final class space/kscience/plotly/models/Layout$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/LayoutLine : space/kscience/dataforge/meta/Scheme, space/kscience/plotly/models/Line { + public static final field Companion Lspace/kscience/plotly/models/LayoutLine$Companion; + public fun ()V + public fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun getDash ()Lspace/kscience/plotly/models/Dash; + public final fun getShape ()Lspace/kscience/plotly/models/LineShape; + public final fun getSmoothing ()Ljava/lang/Number; + public fun getWidth ()Ljava/lang/Number; + public fun getWidthList ()Ljava/util/List; + public final fun setDash (Lspace/kscience/plotly/models/Dash;)V + public final fun setShape (Lspace/kscience/plotly/models/LineShape;)V + public final fun setSmoothing (Ljava/lang/Number;)V + public fun setWidth (Ljava/lang/Number;)V + public fun setWidthList (Ljava/util/List;)V +} + +public final class space/kscience/plotly/models/LayoutLine$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/Legend : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Legend$Companion; + public fun ()V + public final fun font (Lkotlin/jvm/functions/Function1;)V + public final fun getBgcolor ()Lspace/kscience/plotly/models/Color; + public final fun getBordercolor ()Lspace/kscience/plotly/models/Color; + public final fun getBorderwidth ()Ljava/lang/Number; + public final fun getFont ()Lspace/kscience/plotly/models/Font; + public final fun getOrientation ()Lspace/kscience/plotly/models/LegendOrientation; + public final fun getTraceorder ()Lspace/kscience/plotly/models/TraceOrder; + public final fun getX ()Ljava/lang/Number; + public final fun getXanchor ()Lspace/kscience/plotly/models/XAnchor; + public final fun getY ()Ljava/lang/Number; + public final fun getYanchor ()Lspace/kscience/plotly/models/YAnchor; + public final fun setBorderwidth (Ljava/lang/Number;)V + public final fun setFont (Lspace/kscience/plotly/models/Font;)V + public final fun setOrientation (Lspace/kscience/plotly/models/LegendOrientation;)V + public final fun setTraceorder (Lspace/kscience/plotly/models/TraceOrder;)V + public final fun setX (Ljava/lang/Number;)V + public final fun setXanchor (Lspace/kscience/plotly/models/XAnchor;)V + public final fun setY (Ljava/lang/Number;)V + public final fun setYanchor (Lspace/kscience/plotly/models/YAnchor;)V +} + +public final class space/kscience/plotly/models/Legend$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/LegendOrientation : java/lang/Enum { + public static final field horizontal Lspace/kscience/plotly/models/LegendOrientation; + public static final field vertical Lspace/kscience/plotly/models/LegendOrientation; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/LegendOrientation; + public static fun values ()[Lspace/kscience/plotly/models/LegendOrientation; +} + +public abstract interface class space/kscience/plotly/models/Line { + public abstract fun getColor ()Lspace/kscience/plotly/models/Color; + public abstract fun getWidth ()Ljava/lang/Number; + public abstract fun getWidthList ()Ljava/util/List; + public abstract fun setWidth (Ljava/lang/Number;)V + public abstract fun setWidthList (Ljava/util/List;)V +} + +public final class space/kscience/plotly/models/LineShape : java/lang/Enum { + public static final field hv Lspace/kscience/plotly/models/LineShape; + public static final field hvh Lspace/kscience/plotly/models/LineShape; + public static final field linear Lspace/kscience/plotly/models/LineShape; + public static final field spline Lspace/kscience/plotly/models/LineShape; + public static final field vh Lspace/kscience/plotly/models/LineShape; + public static final field vhv Lspace/kscience/plotly/models/LineShape; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/LineShape; + public static fun values ()[Lspace/kscience/plotly/models/LineShape; +} + +public final class space/kscience/plotly/models/Margin : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Margin$Companion; + public fun ()V + public final fun getAutoexpand ()Ljava/lang/Boolean; + public final fun getB ()Ljava/lang/Number; + public final fun getL ()Ljava/lang/Number; + public final fun getPad ()Ljava/lang/Number; + public final fun getR ()Ljava/lang/Number; + public final fun getT ()Ljava/lang/Number; + public final fun setAutoexpand (Ljava/lang/Boolean;)V + public final fun setB (Ljava/lang/Number;)V + public final fun setL (Ljava/lang/Number;)V + public final fun setPad (Ljava/lang/Number;)V + public final fun setR (Ljava/lang/Number;)V + public final fun setT (Ljava/lang/Number;)V +} + +public final class space/kscience/plotly/models/Margin$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/Marker : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Marker$Companion; + public fun ()V + public final fun colorbar (Lkotlin/jvm/functions/Function1;)V + public final fun colors (Ljava/lang/Iterable;)V + public final fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun getColorbar ()Lspace/kscience/plotly/models/ColorBar; + public final fun getGradient ()Lspace/kscience/plotly/models/Gradient; + public final fun getLine ()Lspace/kscience/plotly/models/MarkerLine; + public final fun getMaxdisplayed ()I + public final fun getOpacitiesList ()Ljava/util/List; + public final fun getOpacity ()Ljava/lang/Number; + public final fun getOutliercolor ()Lspace/kscience/plotly/models/Color; + public final fun getPieColors ()Ljava/util/List; + public final fun getSize ()Ljava/lang/Number; + public final fun getSizemin ()Ljava/lang/Number; + public final fun getSizemode ()Lspace/kscience/plotly/models/SizeMode; + public final fun getSizeref ()Ljava/lang/Number; + public final fun getSizesList ()Ljava/util/List; + public final fun getSymbol ()Lspace/kscience/plotly/models/Symbol; + public final fun getSymbolsList ()Ljava/util/List; + public final fun gradient (Lkotlin/jvm/functions/Function1;)V + public final fun line (Lkotlin/jvm/functions/Function1;)V + public final fun setColorbar (Lspace/kscience/plotly/models/ColorBar;)V + public final fun setGradient (Lspace/kscience/plotly/models/Gradient;)V + public final fun setLine (Lspace/kscience/plotly/models/MarkerLine;)V + public final fun setMaxdisplayed (I)V + public final fun setOpacitiesList (Ljava/util/List;)V + public final fun setOpacity (Ljava/lang/Number;)V + public final fun setPieColors (Ljava/util/List;)V + public final fun setSize (Ljava/lang/Number;)V + public final fun setSizemin (Ljava/lang/Number;)V + public final fun setSizemode (Lspace/kscience/plotly/models/SizeMode;)V + public final fun setSizeref (Ljava/lang/Number;)V + public final fun setSizesList (Ljava/util/List;)V + public final fun setSymbol (Lspace/kscience/plotly/models/Symbol;)V + public final fun setSymbolsList (Ljava/util/List;)V +} + +public final class space/kscience/plotly/models/Marker$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/MarkerLine : space/kscience/dataforge/meta/Scheme, space/kscience/plotly/models/Line { + public static final field Companion Lspace/kscience/plotly/models/MarkerLine$Companion; + public fun ()V + public final fun colors (Ljava/lang/Iterable;)V + public final fun getAutocolorscale ()Ljava/lang/Boolean; + public final fun getCauto ()Ljava/lang/Boolean; + public final fun getCmax ()Ljava/lang/Number; + public final fun getCmid ()Ljava/lang/Number; + public final fun getCmin ()Ljava/lang/Number; + public fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun getColorscale ()Lspace/kscience/dataforge/meta/Value; + public final fun getOutliercolor ()Lspace/kscience/plotly/models/Color; + public final fun getOutlierwidth ()Ljava/lang/Number; + public final fun getReversescale ()Ljava/lang/Boolean; + public fun getWidth ()Ljava/lang/Number; + public fun getWidthList ()Ljava/util/List; + public final fun setAutocolorscale (Ljava/lang/Boolean;)V + public final fun setCauto (Ljava/lang/Boolean;)V + public final fun setCmax (Ljava/lang/Number;)V + public final fun setCmid (Ljava/lang/Number;)V + public final fun setCmin (Ljava/lang/Number;)V + public final fun setColorscale (Lspace/kscience/dataforge/meta/Value;)V + public final fun setOutlierwidth (Ljava/lang/Number;)V + public final fun setReversescale (Ljava/lang/Boolean;)V + public fun setWidth (Ljava/lang/Number;)V + public fun setWidthList (Ljava/util/List;)V +} + +public final class space/kscience/plotly/models/MarkerLine$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/MeanLine : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/MeanLine$Companion; + public fun ()V + public final fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun getVisible ()Ljava/lang/Boolean; + public final fun getWidth ()Ljava/lang/Number; + public final fun setVisible (Ljava/lang/Boolean;)V + public final fun setWidth (Ljava/lang/Number;)V +} + +public final class space/kscience/plotly/models/MeanLine$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/MeasureMode : java/lang/Enum { + public static final field fraction Lspace/kscience/plotly/models/MeasureMode; + public static final field pixels Lspace/kscience/plotly/models/MeasureMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/MeasureMode; + public static fun values ()[Lspace/kscience/plotly/models/MeasureMode; +} + +public final class space/kscience/plotly/models/Orientation : java/lang/Enum { + public static final field h Lspace/kscience/plotly/models/Orientation; + public static final field v Lspace/kscience/plotly/models/Orientation; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/Orientation; + public static fun values ()[Lspace/kscience/plotly/models/Orientation; +} + +public final class space/kscience/plotly/models/Pie : space/kscience/plotly/models/Trace { + public static final field Companion Lspace/kscience/plotly/models/Pie$Companion; + public fun ()V + public final fun getDirection ()Lspace/kscience/plotly/models/PieDirection; + public final fun getDlabel ()Ljava/lang/Number; + public final fun getHole ()Ljava/lang/Number; + public final fun getLabel0 ()Ljava/lang/Number; + public final fun getPull ()Ljava/lang/Number; + public final fun getPullList ()Ljava/util/List; + public final fun getRotation ()Ljava/lang/Number; + public final fun getSort ()Ljava/lang/Boolean; + public final fun getTextinfo ()Lspace/kscience/plotly/models/TextInfo; + public final fun setDirection (Lspace/kscience/plotly/models/PieDirection;)V + public final fun setDlabel (Ljava/lang/Number;)V + public final fun setHole (Ljava/lang/Number;)V + public final fun setLabel0 (Ljava/lang/Number;)V + public final fun setPull (Ljava/lang/Number;)V + public final fun setPullList (Ljava/util/List;)V + public final fun setRotation (Ljava/lang/Number;)V + public final fun setSort (Ljava/lang/Boolean;)V + public final fun setTextinfo (Lspace/kscience/plotly/models/TextInfo;)V +} + +public final class space/kscience/plotly/models/Pie$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/PieDirection : java/lang/Enum { + public static final field clockwise Lspace/kscience/plotly/models/PieDirection; + public static final field counterclockwise Lspace/kscience/plotly/models/PieDirection; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/PieDirection; + public static fun values ()[Lspace/kscience/plotly/models/PieDirection; +} + +public final class space/kscience/plotly/models/QuartileMethod : java/lang/Enum { + public static final field exclusive Lspace/kscience/plotly/models/QuartileMethod; + public static final field inclusive Lspace/kscience/plotly/models/QuartileMethod; + public static final field linear Lspace/kscience/plotly/models/QuartileMethod; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/QuartileMethod; + public static fun values ()[Lspace/kscience/plotly/models/QuartileMethod; +} + +public final class space/kscience/plotly/models/Ref : java/lang/Enum { + public static final field container Lspace/kscience/plotly/models/Ref; + public static final field paper Lspace/kscience/plotly/models/Ref; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/Ref; + public static fun values ()[Lspace/kscience/plotly/models/Ref; +} + +public class space/kscience/plotly/models/Scatter : space/kscience/plotly/models/Trace, space/kscience/plotly/models/SelectedPoints { + public static final field Companion Lspace/kscience/plotly/models/Scatter$Companion; + public fun ()V + public final fun getFill ()Lspace/kscience/plotly/models/FillType; + public final fun getGroupnorm ()Lspace/kscience/plotly/models/GroupNorm; + public final fun getHoveron ()Lspace/kscience/plotly/models/ScatterHoveron; + public final fun getMode ()Lspace/kscience/plotly/models/ScatterMode; + public fun getSelected ()Lspace/kscience/plotly/models/SelectPoints; + public fun getSelectedpoints ()Ljava/util/List; + public final fun getStackgaps ()Lspace/kscience/plotly/models/StackGaps; + public final fun getStackgroup ()Ljava/lang/String; + public fun getUnselected ()Lspace/kscience/plotly/models/SelectPoints; + public final fun getYaxis ()Ljava/lang/String; + public final fun selected (Lkotlin/jvm/functions/Function1;)V + public final fun setFill (Lspace/kscience/plotly/models/FillType;)V + public final fun setGroupnorm (Lspace/kscience/plotly/models/GroupNorm;)V + public final fun setHoveron (Lspace/kscience/plotly/models/ScatterHoveron;)V + public final fun setMode (Lspace/kscience/plotly/models/ScatterMode;)V + public fun setSelected (Lspace/kscience/plotly/models/SelectPoints;)V + public fun setSelectedpoints (Ljava/util/List;)V + public final fun setStackgaps (Lspace/kscience/plotly/models/StackGaps;)V + public final fun setStackgroup (Ljava/lang/String;)V + public fun setUnselected (Lspace/kscience/plotly/models/SelectPoints;)V + public final fun setYaxis (Ljava/lang/String;)V + public final fun unselected (Lkotlin/jvm/functions/Function1;)V +} + +public final class space/kscience/plotly/models/Scatter$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/ScatterGL : space/kscience/plotly/models/Scatter { + public static final field Companion Lspace/kscience/plotly/models/ScatterGL$Companion; + public fun ()V +} + +public final class space/kscience/plotly/models/ScatterGL$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/ScatterHoveron : java/lang/Enum { + public static final field fills Lspace/kscience/plotly/models/ScatterHoveron; + public static final field points Lspace/kscience/plotly/models/ScatterHoveron; + public static final field points+fills Lspace/kscience/plotly/models/ScatterHoveron; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ScatterHoveron; + public static fun values ()[Lspace/kscience/plotly/models/ScatterHoveron; +} + +public final class space/kscience/plotly/models/ScatterMode : java/lang/Enum { + public static final field lines Lspace/kscience/plotly/models/ScatterMode; + public static final field lines+markers Lspace/kscience/plotly/models/ScatterMode; + public static final field lines+markers+text Lspace/kscience/plotly/models/ScatterMode; + public static final field lines+text Lspace/kscience/plotly/models/ScatterMode; + public static final field markers Lspace/kscience/plotly/models/ScatterMode; + public static final field markers+text Lspace/kscience/plotly/models/ScatterMode; + public static final field none Lspace/kscience/plotly/models/ScatterMode; + public static final field text Lspace/kscience/plotly/models/ScatterMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ScatterMode; + public static fun values ()[Lspace/kscience/plotly/models/ScatterMode; +} + +public final class space/kscience/plotly/models/SelectMarker : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/SelectMarker$Companion; + public fun ()V + public final fun getColor ()Lspace/kscience/plotly/models/Color; + public final fun getOpacity ()Ljava/lang/Number; + public final fun getSize ()Ljava/lang/Number; + public final fun setOpacity (Ljava/lang/Number;)V + public final fun setSize (Ljava/lang/Number;)V +} + +public final class space/kscience/plotly/models/SelectMarker$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/SelectPoints : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/SelectPoints$Companion; + public fun ()V + public final fun getMarker ()Lspace/kscience/plotly/models/SelectMarker; + public final fun getTextfont ()Lspace/kscience/plotly/models/Font; + public final fun marker (Lkotlin/jvm/functions/Function1;)V + public final fun setMarker (Lspace/kscience/plotly/models/SelectMarker;)V + public final fun setTextfont (Lspace/kscience/plotly/models/Font;)V + public final fun textfont (Lkotlin/jvm/functions/Function1;)V +} + +public final class space/kscience/plotly/models/SelectPoints$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public abstract interface class space/kscience/plotly/models/SelectedPoints { + public abstract fun getSelected ()Lspace/kscience/plotly/models/SelectPoints; + public abstract fun getSelectedpoints ()Ljava/util/List; + public abstract fun getUnselected ()Lspace/kscience/plotly/models/SelectPoints; + public abstract fun setSelected (Lspace/kscience/plotly/models/SelectPoints;)V + public abstract fun setSelectedpoints (Ljava/util/List;)V + public abstract fun setUnselected (Lspace/kscience/plotly/models/SelectPoints;)V +} + +public final class space/kscience/plotly/models/Shape : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Shape$Companion; + public fun ()V + public final fun endXY (Ljava/lang/Number;Ljava/lang/Number;)V + public final fun getEditable ()Ljava/lang/Boolean; + public final fun getFillcolor ()Lspace/kscience/plotly/models/Color; + public final fun getFillrule ()Lspace/kscience/plotly/models/ShapeFillRule; + public final fun getLayer ()Lspace/kscience/plotly/models/ShapeLayer; + public final fun getLine ()Lspace/kscience/plotly/models/LayoutLine; + public final fun getName ()Ljava/lang/String; + public final fun getOpacity ()Ljava/lang/Number; + public final fun getPath ()Ljava/lang/String; + public final fun getTemplateitemname ()Ljava/lang/String; + public final fun getType ()Lspace/kscience/plotly/models/ShapeType; + public final fun getVisible ()Ljava/lang/Boolean; + public final fun getX0 ()Lspace/kscience/dataforge/meta/Value; + public final fun getX1 ()Lspace/kscience/dataforge/meta/Value; + public final fun getXanchor ()Lspace/kscience/dataforge/meta/Value; + public final fun getXref ()Ljava/lang/String; + public final fun getXsizemode ()Lspace/kscience/plotly/models/ShapeSizeMode; + public final fun getY0 ()Lspace/kscience/dataforge/meta/Value; + public final fun getY1 ()Lspace/kscience/dataforge/meta/Value; + public final fun getYanchor ()Lspace/kscience/dataforge/meta/Value; + public final fun getYref ()Ljava/lang/String; + public final fun getYsizemode ()Lspace/kscience/plotly/models/ShapeSizeMode; + public final fun line (Lkotlin/jvm/functions/Function1;)V + public final fun setEditable (Ljava/lang/Boolean;)V + public final fun setFillrule (Lspace/kscience/plotly/models/ShapeFillRule;)V + public final fun setLayer (Lspace/kscience/plotly/models/ShapeLayer;)V + public final fun setLine (Lspace/kscience/plotly/models/LayoutLine;)V + public final fun setName (Ljava/lang/String;)V + public final fun setOpacity (Ljava/lang/Number;)V + public final fun setPath (Ljava/lang/String;)V + public final fun setTemplateitemname (Ljava/lang/String;)V + public final fun setType (Lspace/kscience/plotly/models/ShapeType;)V + public final fun setVisible (Ljava/lang/Boolean;)V + public final fun setX0 (Lspace/kscience/dataforge/meta/Value;)V + public final fun setX1 (Lspace/kscience/dataforge/meta/Value;)V + public final fun setXanchor (Lspace/kscience/dataforge/meta/Value;)V + public final fun setXref (Ljava/lang/String;)V + public final fun setXsizemode (Lspace/kscience/plotly/models/ShapeSizeMode;)V + public final fun setY0 (Lspace/kscience/dataforge/meta/Value;)V + public final fun setY1 (Lspace/kscience/dataforge/meta/Value;)V + public final fun setYanchor (Lspace/kscience/dataforge/meta/Value;)V + public final fun setYref (Ljava/lang/String;)V + public final fun setYsizemode (Lspace/kscience/plotly/models/ShapeSizeMode;)V + public final fun startXY (Ljava/lang/Number;Ljava/lang/Number;)V +} + +public final class space/kscience/plotly/models/Shape$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/ShapeFillRule : java/lang/Enum { + public static final field evenodd Lspace/kscience/plotly/models/ShapeFillRule; + public static final field nonzero Lspace/kscience/plotly/models/ShapeFillRule; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ShapeFillRule; + public static fun values ()[Lspace/kscience/plotly/models/ShapeFillRule; +} + +public final class space/kscience/plotly/models/ShapeLayer : java/lang/Enum { + public static final field above Lspace/kscience/plotly/models/ShapeLayer; + public static final field below Lspace/kscience/plotly/models/ShapeLayer; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ShapeLayer; + public static fun values ()[Lspace/kscience/plotly/models/ShapeLayer; +} + +public final class space/kscience/plotly/models/ShapeSizeMode : java/lang/Enum { + public static final field pixel Lspace/kscience/plotly/models/ShapeSizeMode; + public static final field scaled Lspace/kscience/plotly/models/ShapeSizeMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ShapeSizeMode; + public static fun values ()[Lspace/kscience/plotly/models/ShapeSizeMode; +} + +public final class space/kscience/plotly/models/ShapeType : java/lang/Enum { + public static final field circle Lspace/kscience/plotly/models/ShapeType; + public static final field line Lspace/kscience/plotly/models/ShapeType; + public static final field path Lspace/kscience/plotly/models/ShapeType; + public static final field rect Lspace/kscience/plotly/models/ShapeType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ShapeType; + public static fun values ()[Lspace/kscience/plotly/models/ShapeType; +} + +public final class space/kscience/plotly/models/SizeMode : java/lang/Enum { + public static final field area Lspace/kscience/plotly/models/SizeMode; + public static final field diameter Lspace/kscience/plotly/models/SizeMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/SizeMode; + public static fun values ()[Lspace/kscience/plotly/models/SizeMode; +} + +public final class space/kscience/plotly/models/SpanMode : java/lang/Enum { + public static final field hard Lspace/kscience/plotly/models/SpanMode; + public static final field manual Lspace/kscience/plotly/models/SpanMode; + public static final field soft Lspace/kscience/plotly/models/SpanMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/SpanMode; + public static fun values ()[Lspace/kscience/plotly/models/SpanMode; +} + +public final class space/kscience/plotly/models/StackGaps : java/lang/Enum { + public static final field infer zero Lspace/kscience/plotly/models/StackGaps; + public static final field interpolate Lspace/kscience/plotly/models/StackGaps; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/StackGaps; + public static fun values ()[Lspace/kscience/plotly/models/StackGaps; +} + +public final class space/kscience/plotly/models/Symbol : java/lang/Enum { + public static final field circle Lspace/kscience/plotly/models/Symbol; + public static final field cross Lspace/kscience/plotly/models/Symbol; + public static final field cross-thin Lspace/kscience/plotly/models/Symbol; + public static final field line-ns Lspace/kscience/plotly/models/Symbol; + public static final field square-cross Lspace/kscience/plotly/models/Symbol; + public static final field triangle-down Lspace/kscience/plotly/models/Symbol; + public static final field triangle-up Lspace/kscience/plotly/models/Symbol; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/Symbol; + public static fun values ()[Lspace/kscience/plotly/models/Symbol; +} + +public final class space/kscience/plotly/models/Table : space/kscience/plotly/models/Trace { + public static final field Companion Lspace/kscience/plotly/models/Table$Companion; + public fun ()V + public final fun cells (Lkotlin/jvm/functions/Function1;)V + public final fun getCells ()Lspace/kscience/plotly/models/Cells; + public final fun getColumnorder ()Lspace/kscience/plotly/models/TraceValues; + public final fun getColumnwidth ()Lspace/kscience/plotly/models/TraceValues; + public final fun getHeader ()Lspace/kscience/plotly/models/Header; + public final fun getIds ()Lspace/kscience/plotly/models/TraceValues; + public final fun header (Lkotlin/jvm/functions/Function1;)V + public final fun setCells (Lspace/kscience/plotly/models/Cells;)V + public final fun setColumnorder (Lspace/kscience/plotly/models/TraceValues;)V + public final fun setColumnwidth (Lspace/kscience/plotly/models/TraceValues;)V + public final fun setHeader (Lspace/kscience/plotly/models/Header;)V + public final fun setIds (Lspace/kscience/plotly/models/TraceValues;)V +} + +public final class space/kscience/plotly/models/Table$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public abstract interface class space/kscience/plotly/models/Table2D { + public abstract fun getXgap ()Ljava/lang/Number; + public abstract fun getYgap ()Ljava/lang/Number; + public abstract fun getZsmooth ()Lspace/kscience/plotly/models/ZsmoothType; + public abstract fun setXgap (Ljava/lang/Number;)V + public abstract fun setYgap (Ljava/lang/Number;)V + public abstract fun setZsmooth (Lspace/kscience/plotly/models/ZsmoothType;)V +} + +public final class space/kscience/plotly/models/Text : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Text$Companion; + public fun ()V + public final fun font (Lkotlin/jvm/functions/Function1;)V + public final fun getAlign ()Lspace/kscience/plotly/models/HorizontalAlign; + public final fun getArrowcolor ()Lspace/kscience/plotly/models/Color; + public final fun getAx ()Lspace/kscience/dataforge/meta/Value; + public final fun getAy ()Lspace/kscience/dataforge/meta/Value; + public final fun getBgcolor ()Lspace/kscience/plotly/models/Color; + public final fun getBordercolor ()Lspace/kscience/plotly/models/Color; + public final fun getFont ()Lspace/kscience/plotly/models/Font; + public final fun getHeight ()Ljava/lang/Number; + public final fun getOpacity ()Ljava/lang/Number; + public final fun getShowarrow ()Ljava/lang/Boolean; + public final fun getStandoff ()Ljava/lang/Number; + public final fun getText ()Ljava/lang/String; + public final fun getTextangle ()Ljava/lang/Number; + public final fun getValign ()Lspace/kscience/plotly/models/VerticalAlign; + public final fun getVisible ()Ljava/lang/Boolean; + public final fun getWidth ()Ljava/lang/Number; + public final fun getX ()Lspace/kscience/dataforge/meta/Value; + public final fun getXanchor ()Lspace/kscience/plotly/models/XAnchor; + public final fun getXref ()Ljava/lang/String; + public final fun getY ()Lspace/kscience/dataforge/meta/Value; + public final fun getYanchor ()Lspace/kscience/plotly/models/YAnchor; + public final fun getYref ()Ljava/lang/String; + public final fun position (Ljava/lang/Number;Ljava/lang/Number;)V + public final fun setAlign (Lspace/kscience/plotly/models/HorizontalAlign;)V + public final fun setAx (Lspace/kscience/dataforge/meta/Value;)V + public final fun setAy (Lspace/kscience/dataforge/meta/Value;)V + public final fun setFont (Lspace/kscience/plotly/models/Font;)V + public final fun setHeight (Ljava/lang/Number;)V + public final fun setOpacity (Ljava/lang/Number;)V + public final fun setShowarrow (Ljava/lang/Boolean;)V + public final fun setStandoff (Ljava/lang/Number;)V + public final fun setText (Ljava/lang/String;)V + public final fun setTextangle (Ljava/lang/Number;)V + public final fun setValign (Lspace/kscience/plotly/models/VerticalAlign;)V + public final fun setVisible (Ljava/lang/Boolean;)V + public final fun setWidth (Ljava/lang/Number;)V + public final fun setX (Lspace/kscience/dataforge/meta/Value;)V + public final fun setXanchor (Lspace/kscience/plotly/models/XAnchor;)V + public final fun setXref (Ljava/lang/String;)V + public final fun setY (Lspace/kscience/dataforge/meta/Value;)V + public final fun setYanchor (Lspace/kscience/plotly/models/YAnchor;)V + public final fun setYref (Ljava/lang/String;)V +} + +public final class space/kscience/plotly/models/Text$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/TextInfo : java/lang/Enum { + public static final field label Lspace/kscience/plotly/models/TextInfo; + public static final field label+percent Lspace/kscience/plotly/models/TextInfo; + public static final field label+text Lspace/kscience/plotly/models/TextInfo; + public static final field label+text+percent Lspace/kscience/plotly/models/TextInfo; + public static final field label+text+value Lspace/kscience/plotly/models/TextInfo; + public static final field label+text+value+percent Lspace/kscience/plotly/models/TextInfo; + public static final field label+value Lspace/kscience/plotly/models/TextInfo; + public static final field label+value+percent Lspace/kscience/plotly/models/TextInfo; + public static final field none Lspace/kscience/plotly/models/TextInfo; + public static final field percent Lspace/kscience/plotly/models/TextInfo; + public static final field text Lspace/kscience/plotly/models/TextInfo; + public static final field text+percent Lspace/kscience/plotly/models/TextInfo; + public static final field text+value Lspace/kscience/plotly/models/TextInfo; + public static final field text+value+percent Lspace/kscience/plotly/models/TextInfo; + public static final field value Lspace/kscience/plotly/models/TextInfo; + public static final field value+percent Lspace/kscience/plotly/models/TextInfo; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/TextInfo; + public static fun values ()[Lspace/kscience/plotly/models/TextInfo; +} + +public final class space/kscience/plotly/models/TextPosition : java/lang/Enum { + public static final field auto Lspace/kscience/plotly/models/TextPosition; + public static final field bottom center Lspace/kscience/plotly/models/TextPosition; + public static final field bottom left Lspace/kscience/plotly/models/TextPosition; + public static final field bottom right Lspace/kscience/plotly/models/TextPosition; + public static final field inside Lspace/kscience/plotly/models/TextPosition; + public static final field middle center Lspace/kscience/plotly/models/TextPosition; + public static final field middle left Lspace/kscience/plotly/models/TextPosition; + public static final field middle right Lspace/kscience/plotly/models/TextPosition; + public static final field none Lspace/kscience/plotly/models/TextPosition; + public static final field outside Lspace/kscience/plotly/models/TextPosition; + public static final field top center Lspace/kscience/plotly/models/TextPosition; + public static final field top left Lspace/kscience/plotly/models/TextPosition; + public static final field top right Lspace/kscience/plotly/models/TextPosition; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/TextPosition; + public static fun values ()[Lspace/kscience/plotly/models/TextPosition; +} + +public final class space/kscience/plotly/models/TickMode : java/lang/Enum { + public static final field array Lspace/kscience/plotly/models/TickMode; + public static final field auto Lspace/kscience/plotly/models/TickMode; + public static final field linear Lspace/kscience/plotly/models/TickMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/TickMode; + public static fun values ()[Lspace/kscience/plotly/models/TickMode; +} + +public final class space/kscience/plotly/models/Ticks : java/lang/Enum { + public static final field "" Lspace/kscience/plotly/models/Ticks; + public static final field inside Lspace/kscience/plotly/models/Ticks; + public static final field outside Lspace/kscience/plotly/models/Ticks; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/Ticks; + public static fun values ()[Lspace/kscience/plotly/models/Ticks; +} + +public final class space/kscience/plotly/models/Title : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Title$Companion; + public fun ()V + public final fun font (Lkotlin/jvm/functions/Function1;)V + public final fun getFont ()Lspace/kscience/plotly/models/Font; + public final fun getPad ()Lspace/kscience/plotly/models/Margin; + public final fun getText ()Ljava/lang/String; + public final fun getX ()Ljava/lang/Number; + public final fun getXanchor ()Lspace/kscience/plotly/models/XAnchor; + public final fun getXref ()Lspace/kscience/plotly/models/Ref; + public final fun getY ()Ljava/lang/Number; + public final fun getYanchor ()Lspace/kscience/plotly/models/YAnchor; + public final fun getYref ()Lspace/kscience/plotly/models/Ref; + public final fun pad (Lkotlin/jvm/functions/Function1;)V + public final fun setFont (Lspace/kscience/plotly/models/Font;)V + public final fun setPad (Lspace/kscience/plotly/models/Margin;)V + public final fun setText (Ljava/lang/String;)V + public final fun setX (Ljava/lang/Number;)V + public final fun setXanchor (Lspace/kscience/plotly/models/XAnchor;)V + public final fun setXref (Lspace/kscience/plotly/models/Ref;)V + public final fun setY (Ljava/lang/Number;)V + public final fun setYanchor (Lspace/kscience/plotly/models/YAnchor;)V + public final fun setYref (Lspace/kscience/plotly/models/Ref;)V +} + +public final class space/kscience/plotly/models/Title$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public class space/kscience/plotly/models/Trace : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/Trace$Companion; + public static final field TEXT_AXIS Ljava/lang/String; + public static final field X_AXIS Ljava/lang/String; + public static final field Y_AXIS Ljava/lang/String; + public static final field Z_AXIS Ljava/lang/String; + public fun ()V + public final fun axis (Ljava/lang/String;)Lspace/kscience/plotly/models/TraceValues; + public final fun colorbar (Lkotlin/jvm/functions/Function1;)V + public final fun domain (Lkotlin/jvm/functions/Function1;)V + public final fun error_x (Lkotlin/jvm/functions/Function1;)V + public final fun error_y (Lkotlin/jvm/functions/Function1;)V + public final fun getAxis ()Lkotlin/properties/ReadOnlyProperty; + public final fun getCliponaxis ()Ljava/lang/Boolean; + public final fun getColorbar ()Lspace/kscience/plotly/models/ColorBar; + public final fun getColorscale ()Lspace/kscience/dataforge/meta/Value; + public final fun getConnectgaps ()Ljava/lang/Boolean; + public final fun getDomain ()Lspace/kscience/plotly/models/Domain; + public final fun getDx ()Ljava/lang/Number; + public final fun getDy ()Ljava/lang/Number; + public final fun getError_x ()Lspace/kscience/plotly/models/Error; + public final fun getError_y ()Lspace/kscience/plotly/models/Error; + public final fun getFillcolor ()Lspace/kscience/plotly/models/Color; + public final fun getHoverinfo ()Ljava/lang/String; + public final fun getHoverlabel ()Lspace/kscience/plotly/models/Hoverlabel; + public final fun getHovertext ()Lspace/kscience/plotly/models/TraceValues; + public final fun getLabels ()Ljava/util/List; + public final fun getLegendgroup ()Ljava/lang/String; + public final fun getLine ()Lspace/kscience/plotly/models/LayoutLine; + public final fun getMarker ()Lspace/kscience/plotly/models/Marker; + public final fun getName ()Ljava/lang/String; + public final fun getOpacity ()Ljava/lang/Number; + public final fun getOrientation ()Lspace/kscience/plotly/models/Orientation; + public final fun getReversescale ()Ljava/lang/Boolean; + public final fun getScalegroup ()Ljava/lang/String; + public final fun getShowlegend ()Ljava/lang/Boolean; + public final fun getShowscale ()Ljava/lang/Boolean; + public final fun getText ()Lspace/kscience/plotly/models/TraceValues; + public final fun getTextfont ()Lspace/kscience/plotly/models/Font; + public final fun getTextposition ()Lspace/kscience/plotly/models/TextPosition; + public final fun getTextpositionsList ()Ljava/util/List; + public final fun getTranspose ()Ljava/lang/Boolean; + public final fun getType ()Lspace/kscience/plotly/models/TraceType; + public final fun getValues ()Ljava/util/List; + public final fun getVisible ()Lspace/kscience/plotly/models/Visible; + public final fun getX ()Lspace/kscience/plotly/models/TraceValues; + public final fun getX0 ()Lspace/kscience/dataforge/meta/Value; + public final fun getXcalendar ()Lspace/kscience/plotly/models/Calendar; + public final fun getY ()Lspace/kscience/plotly/models/TraceValues; + public final fun getY0 ()Lspace/kscience/dataforge/meta/Value; + public final fun getYcalendar ()Lspace/kscience/plotly/models/Calendar; + public final fun getZ ()Lspace/kscience/plotly/models/TraceValues; + public final fun getZauto ()Ljava/lang/Boolean; + public final fun getZmax ()Ljava/lang/Number; + public final fun getZmid ()Ljava/lang/Number; + public final fun getZmin ()Ljava/lang/Number; + public final fun hoverlabel (Lkotlin/jvm/functions/Function1;)V + public final fun labels (Ljava/lang/Iterable;)V + public final fun line (Lkotlin/jvm/functions/Function1;)V + public final fun marker (Lkotlin/jvm/functions/Function1;)V + public final fun setCliponaxis (Ljava/lang/Boolean;)V + public final fun setColorbar (Lspace/kscience/plotly/models/ColorBar;)V + public final fun setColorscale (Lspace/kscience/dataforge/meta/Value;)V + public final fun setConnectgaps (Ljava/lang/Boolean;)V + public final fun setDomain (Lspace/kscience/plotly/models/Domain;)V + public final fun setDx (Ljava/lang/Number;)V + public final fun setDy (Ljava/lang/Number;)V + public final fun setError_x (Lspace/kscience/plotly/models/Error;)V + public final fun setError_y (Lspace/kscience/plotly/models/Error;)V + public final fun setHoverinfo (Ljava/lang/String;)V + public final fun setHoverlabel (Lspace/kscience/plotly/models/Hoverlabel;)V + public final fun setLabels (Ljava/util/List;)V + public final fun setLegendgroup (Ljava/lang/String;)V + public final fun setLine (Lspace/kscience/plotly/models/LayoutLine;)V + public final fun setMarker (Lspace/kscience/plotly/models/Marker;)V + public final fun setName (Ljava/lang/String;)V + public final fun setOpacity (Ljava/lang/Number;)V + public final fun setOrientation (Lspace/kscience/plotly/models/Orientation;)V + public final fun setReversescale (Ljava/lang/Boolean;)V + public final fun setScalegroup (Ljava/lang/String;)V + public final fun setShowlegend (Ljava/lang/Boolean;)V + public final fun setShowscale (Ljava/lang/Boolean;)V + public final fun setTextfont (Lspace/kscience/plotly/models/Font;)V + public final fun setTextposition (Lspace/kscience/plotly/models/TextPosition;)V + public final fun setTextpositionsList (Ljava/util/List;)V + public final fun setTranspose (Ljava/lang/Boolean;)V + public final fun setType (Lspace/kscience/plotly/models/TraceType;)V + public final fun setValues (Ljava/util/List;)V + public final fun setVisible (Lspace/kscience/plotly/models/Visible;)V + public final fun setX0 (Lspace/kscience/dataforge/meta/Value;)V + public final fun setXcalendar (Lspace/kscience/plotly/models/Calendar;)V + public final fun setY0 (Lspace/kscience/dataforge/meta/Value;)V + public final fun setYcalendar (Lspace/kscience/plotly/models/Calendar;)V + public final fun setZauto (Ljava/lang/Boolean;)V + public final fun setZmax (Ljava/lang/Number;)V + public final fun setZmid (Ljava/lang/Number;)V + public final fun setZmin (Ljava/lang/Number;)V + public final fun textfont (Lkotlin/jvm/functions/Function1;)V + public final fun values (Ljava/lang/Iterable;)V +} + +public final class space/kscience/plotly/models/Trace$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/TraceKt { + public static final fun invoke (Lspace/kscience/dataforge/meta/SchemeSpec;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/models/Trace; + public static synthetic fun invoke$default (Lspace/kscience/dataforge/meta/SchemeSpec;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/plotly/models/Trace; +} + +public final class space/kscience/plotly/models/TraceOrder : java/lang/Enum { + public static final field normal Lspace/kscience/plotly/models/TraceOrder; + public static final field reversed Lspace/kscience/plotly/models/TraceOrder; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/TraceOrder; + public static fun values ()[Lspace/kscience/plotly/models/TraceOrder; +} + +public final class space/kscience/plotly/models/TraceType : java/lang/Enum { + public static final field bar Lspace/kscience/plotly/models/TraceType; + public static final field box Lspace/kscience/plotly/models/TraceType; + public static final field candlestick Lspace/kscience/plotly/models/TraceType; + public static final field choropleth Lspace/kscience/plotly/models/TraceType; + public static final field choroplethmapbox Lspace/kscience/plotly/models/TraceType; + public static final field cone Lspace/kscience/plotly/models/TraceType; + public static final field contour Lspace/kscience/plotly/models/TraceType; + public static final field heatmap Lspace/kscience/plotly/models/TraceType; + public static final field heatmapgl Lspace/kscience/plotly/models/TraceType; + public static final field histogram Lspace/kscience/plotly/models/TraceType; + public static final field histogram2d Lspace/kscience/plotly/models/TraceType; + public static final field histogram2dcontour Lspace/kscience/plotly/models/TraceType; + public static final field image Lspace/kscience/plotly/models/TraceType; + public static final field isosurface Lspace/kscience/plotly/models/TraceType; + public static final field mesh3d Lspace/kscience/plotly/models/TraceType; + public static final field ohlc Lspace/kscience/plotly/models/TraceType; + public static final field pie Lspace/kscience/plotly/models/TraceType; + public static final field scatter Lspace/kscience/plotly/models/TraceType; + public static final field scatter3d Lspace/kscience/plotly/models/TraceType; + public static final field scattergeo Lspace/kscience/plotly/models/TraceType; + public static final field scattergl Lspace/kscience/plotly/models/TraceType; + public static final field scattermapbox Lspace/kscience/plotly/models/TraceType; + public static final field streamtube Lspace/kscience/plotly/models/TraceType; + public static final field surface Lspace/kscience/plotly/models/TraceType; + public static final field table Lspace/kscience/plotly/models/TraceType; + public static final field violin Lspace/kscience/plotly/models/TraceType; + public static final field volume Lspace/kscience/plotly/models/TraceType; + public static final field waterfall Lspace/kscience/plotly/models/TraceType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/TraceType; + public static fun values ()[Lspace/kscience/plotly/models/TraceType; +} + +public final class space/kscience/plotly/models/TraceValues { + public final fun getDoubles ()[D + public final fun getNumbers ()Ljava/lang/Iterable; + public final fun getOwner ()Lspace/kscience/dataforge/meta/Scheme; + public final fun getStrings ()Ljava/lang/Iterable; + public final fun getValue ()Lspace/kscience/dataforge/meta/Value; + public final fun invoke (Ljava/util/List;)V + public final fun invoke ([Ljava/lang/Number;)V + public final fun invoke ([Ljava/lang/String;)V + public final fun set (Ljava/lang/Object;)V + public final fun setDoubles ([D)V + public final fun setNumbers (Ljava/lang/Iterable;)V + public final fun setStrings (Ljava/lang/Iterable;)V + public final fun setValue (Lspace/kscience/dataforge/meta/Value;)V +} + +public final class space/kscience/plotly/models/VerticalAlign : java/lang/Enum { + public static final field bottom Lspace/kscience/plotly/models/VerticalAlign; + public static final field middle Lspace/kscience/plotly/models/VerticalAlign; + public static final field top Lspace/kscience/plotly/models/VerticalAlign; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/VerticalAlign; + public static fun values ()[Lspace/kscience/plotly/models/VerticalAlign; +} + +public final class space/kscience/plotly/models/Violin : space/kscience/plotly/models/Trace { + public static final field Companion Lspace/kscience/plotly/models/Violin$Companion; + public fun ()V + public final fun box (Lkotlin/jvm/functions/Function1;)V + public final fun getBox ()Lspace/kscience/plotly/models/ViolinBox; + public final fun getHoveron ()Lspace/kscience/plotly/models/ViolinHoveron; + public final fun getJitter ()Ljava/lang/Number; + public final fun getMeanline ()Lspace/kscience/plotly/models/MeanLine; + public final fun getPointpos ()Ljava/lang/Number; + public final fun getPoints ()Lspace/kscience/plotly/models/ViolinPoints; + public final fun getScalemode ()Lspace/kscience/plotly/models/ViolinScaleMode; + public final fun getSide ()Lspace/kscience/plotly/models/ViolinSide; + public final fun getSpan ()Ljava/util/List; + public final fun getSpanmode ()Lspace/kscience/plotly/models/SpanMode; + public final fun meanline (Lkotlin/jvm/functions/Function1;)V + public final fun setBox (Lspace/kscience/plotly/models/ViolinBox;)V + public final fun setHoveron (Lspace/kscience/plotly/models/ViolinHoveron;)V + public final fun setJitter (Ljava/lang/Number;)V + public final fun setMeanline (Lspace/kscience/plotly/models/MeanLine;)V + public final fun setPointpos (Ljava/lang/Number;)V + public final fun setPoints (Lspace/kscience/plotly/models/ViolinPoints;)V + public final fun setScalemode (Lspace/kscience/plotly/models/ViolinScaleMode;)V + public final fun setSide (Lspace/kscience/plotly/models/ViolinSide;)V + public final fun setSpan (Ljava/util/List;)V + public final fun setSpanmode (Lspace/kscience/plotly/models/SpanMode;)V + public final fun span (Ljava/lang/Iterable;)V +} + +public final class space/kscience/plotly/models/Violin$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/ViolinBox : space/kscience/dataforge/meta/Scheme { + public static final field Companion Lspace/kscience/plotly/models/ViolinBox$Companion; + public fun ()V + public final fun getFillcolor ()Lspace/kscience/plotly/models/Color; + public final fun getVisible ()Ljava/lang/Boolean; + public final fun getWidth ()Ljava/lang/Number; + public final fun setVisible (Ljava/lang/Boolean;)V + public final fun setWidth (Ljava/lang/Number;)V +} + +public final class space/kscience/plotly/models/ViolinBox$Companion : space/kscience/dataforge/meta/SchemeSpec { +} + +public final class space/kscience/plotly/models/ViolinHoveron : java/lang/Enum { + public static final field all Lspace/kscience/plotly/models/ViolinHoveron; + public static final field kde Lspace/kscience/plotly/models/ViolinHoveron; + public static final field points Lspace/kscience/plotly/models/ViolinHoveron; + public static final field points+kde Lspace/kscience/plotly/models/ViolinHoveron; + public static final field violins Lspace/kscience/plotly/models/ViolinHoveron; + public static final field violins+kde Lspace/kscience/plotly/models/ViolinHoveron; + public static final field violins+points Lspace/kscience/plotly/models/ViolinHoveron; + public static final field violins+points+kde Lspace/kscience/plotly/models/ViolinHoveron; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ViolinHoveron; + public static fun values ()[Lspace/kscience/plotly/models/ViolinHoveron; +} + +public final class space/kscience/plotly/models/ViolinMode : java/lang/Enum { + public static final field group Lspace/kscience/plotly/models/ViolinMode; + public static final field overlay Lspace/kscience/plotly/models/ViolinMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ViolinMode; + public static fun values ()[Lspace/kscience/plotly/models/ViolinMode; +} + +public final class space/kscience/plotly/models/ViolinPoints : java/lang/Enum { + public static final field all Lspace/kscience/plotly/models/ViolinPoints; + public static final field false Lspace/kscience/plotly/models/ViolinPoints; + public static final field outliers Lspace/kscience/plotly/models/ViolinPoints; + public static final field suspectedoutliers Lspace/kscience/plotly/models/ViolinPoints; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ViolinPoints; + public static fun values ()[Lspace/kscience/plotly/models/ViolinPoints; +} + +public final class space/kscience/plotly/models/ViolinScaleMode : java/lang/Enum { + public static final field count Lspace/kscience/plotly/models/ViolinScaleMode; + public static final field width Lspace/kscience/plotly/models/ViolinScaleMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ViolinScaleMode; + public static fun values ()[Lspace/kscience/plotly/models/ViolinScaleMode; +} + +public final class space/kscience/plotly/models/ViolinSide : java/lang/Enum { + public static final field both Lspace/kscience/plotly/models/ViolinSide; + public static final field negative Lspace/kscience/plotly/models/ViolinSide; + public static final field positive Lspace/kscience/plotly/models/ViolinSide; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ViolinSide; + public static fun values ()[Lspace/kscience/plotly/models/ViolinSide; +} + +public final class space/kscience/plotly/models/Visible : java/lang/Enum { + public static final field false Lspace/kscience/plotly/models/Visible; + public static final field legendonly Lspace/kscience/plotly/models/Visible; + public static final field true Lspace/kscience/plotly/models/Visible; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/Visible; + public static fun values ()[Lspace/kscience/plotly/models/Visible; +} + +public final class space/kscience/plotly/models/XAnchor : java/lang/Enum { + public static final field auto Lspace/kscience/plotly/models/XAnchor; + public static final field center Lspace/kscience/plotly/models/XAnchor; + public static final field left Lspace/kscience/plotly/models/XAnchor; + public static final field right Lspace/kscience/plotly/models/XAnchor; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/XAnchor; + public static fun values ()[Lspace/kscience/plotly/models/XAnchor; +} + +public final class space/kscience/plotly/models/XPeriodAlignment : java/lang/Enum { + public static final field end Lspace/kscience/plotly/models/XPeriodAlignment; + public static final field middle Lspace/kscience/plotly/models/XPeriodAlignment; + public static final field start Lspace/kscience/plotly/models/XPeriodAlignment; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/XPeriodAlignment; + public static fun values ()[Lspace/kscience/plotly/models/XPeriodAlignment; +} + +public final class space/kscience/plotly/models/YAnchor : java/lang/Enum { + public static final field auto Lspace/kscience/plotly/models/YAnchor; + public static final field bottom Lspace/kscience/plotly/models/YAnchor; + public static final field middle Lspace/kscience/plotly/models/YAnchor; + public static final field top Lspace/kscience/plotly/models/YAnchor; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/YAnchor; + public static fun values ()[Lspace/kscience/plotly/models/YAnchor; +} + +public final class space/kscience/plotly/models/ZsmoothType : java/lang/Enum { + public static final field best Lspace/kscience/plotly/models/ZsmoothType; + public static final field false Lspace/kscience/plotly/models/ZsmoothType; + public static final field fast Lspace/kscience/plotly/models/ZsmoothType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/models/ZsmoothType; + public static fun values ()[Lspace/kscience/plotly/models/ZsmoothType; +} + +public final class space/kscience/plotly/palettes/T10 { + public static final field BLUE Ljava/lang/String; + public static final field BROWN Ljava/lang/String; + public static final field CYAN Ljava/lang/String; + public static final field GRAY Ljava/lang/String; + public static final field GREEN Ljava/lang/String; + public static final field INSTANCE Lspace/kscience/plotly/palettes/T10; + public static final field OLIVE Ljava/lang/String; + public static final field ORANGE Ljava/lang/String; + public static final field PINK Ljava/lang/String; + public static final field PURPLE Ljava/lang/String; + public static final field RED Ljava/lang/String; +} + +public final class space/kscience/plotly/palettes/Xkcd { + public static final field ACID_GREEN Ljava/lang/String; + public static final field ADOBE Ljava/lang/String; + public static final field ALGAE Ljava/lang/String; + public static final field ALGAE_GREEN Ljava/lang/String; + public static final field ALMOST_BLACK Ljava/lang/String; + public static final field AMBER Ljava/lang/String; + public static final field AMETHYST Ljava/lang/String; + public static final field APPLE Ljava/lang/String; + public static final field APPLE_GREEN Ljava/lang/String; + public static final field APRICOT Ljava/lang/String; + public static final field AQUA Ljava/lang/String; + public static final field AQUAMARINE Ljava/lang/String; + public static final field AQUA_BLUE Ljava/lang/String; + public static final field AQUA_GREEN Ljava/lang/String; + public static final field AQUA_MARINE Ljava/lang/String; + public static final field ARMY_GREEN Ljava/lang/String; + public static final field ASPARAGUS Ljava/lang/String; + public static final field AUBERGINE Ljava/lang/String; + public static final field AUBURN Ljava/lang/String; + public static final field AVOCADO Ljava/lang/String; + public static final field AVOCADO_GREEN Ljava/lang/String; + public static final field AZUL Ljava/lang/String; + public static final field AZURE Ljava/lang/String; + public static final field BABY_BLUE Ljava/lang/String; + public static final field BABY_GREEN Ljava/lang/String; + public static final field BABY_PINK Ljava/lang/String; + public static final field BABY_POO Ljava/lang/String; + public static final field BABY_POOP Ljava/lang/String; + public static final field BABY_POOP_GREEN Ljava/lang/String; + public static final field BABY_PUKE_GREEN Ljava/lang/String; + public static final field BABY_PURPLE Ljava/lang/String; + public static final field BABY_SHIT_BROWN Ljava/lang/String; + public static final field BABY_SHIT_GREEN Ljava/lang/String; + public static final field BANANA Ljava/lang/String; + public static final field BANANA_YELLOW Ljava/lang/String; + public static final field BARBIE_PINK Ljava/lang/String; + public static final field BARF_GREEN Ljava/lang/String; + public static final field BARNEY Ljava/lang/String; + public static final field BARNEY_PURPLE Ljava/lang/String; + public static final field BATTLESHIP_GREY Ljava/lang/String; + public static final field BEIGE Ljava/lang/String; + public static final field BERRY Ljava/lang/String; + public static final field BILE Ljava/lang/String; + public static final field BLACK Ljava/lang/String; + public static final field BLAND Ljava/lang/String; + public static final field BLOOD Ljava/lang/String; + public static final field BLOOD_ORANGE Ljava/lang/String; + public static final field BLOOD_RED Ljava/lang/String; + public static final field BLUE Ljava/lang/String; + public static final field BLUEBERRY Ljava/lang/String; + public static final field BLUEGREEN Ljava/lang/String; + public static final field BLUEGREY Ljava/lang/String; + public static final field BLUEY_GREEN Ljava/lang/String; + public static final field BLUEY_GREY Ljava/lang/String; + public static final field BLUEY_PURPLE Ljava/lang/String; + public static final field BLUE_BLUE Ljava/lang/String; + public static final field BLUE_GREEN Ljava/lang/String; + public static final field BLUE_GREY Ljava/lang/String; + public static final field BLUE_PURPLE Ljava/lang/String; + public static final field BLUE_VIOLET Ljava/lang/String; + public static final field BLUE_WITH_A_HINT_OF_PURPLE Ljava/lang/String; + public static final field BLUISH Ljava/lang/String; + public static final field BLUISH_GREEN Ljava/lang/String; + public static final field BLUISH_GREY Ljava/lang/String; + public static final field BLUISH_PURPLE Ljava/lang/String; + public static final field BLURPLE Ljava/lang/String; + public static final field BLUSH Ljava/lang/String; + public static final field BLUSH_PINK Ljava/lang/String; + public static final field BOOGER Ljava/lang/String; + public static final field BOOGER_GREEN Ljava/lang/String; + public static final field BORDEAUX Ljava/lang/String; + public static final field BORING_GREEN Ljava/lang/String; + public static final field BOTTLE_GREEN Ljava/lang/String; + public static final field BRICK Ljava/lang/String; + public static final field BRICK_ORANGE Ljava/lang/String; + public static final field BRICK_RED Ljava/lang/String; + public static final field BRIGHT_AQUA Ljava/lang/String; + public static final field BRIGHT_BLUE Ljava/lang/String; + public static final field BRIGHT_CYAN Ljava/lang/String; + public static final field BRIGHT_GREEN Ljava/lang/String; + public static final field BRIGHT_LAVENDER Ljava/lang/String; + public static final field BRIGHT_LIGHT_BLUE Ljava/lang/String; + public static final field BRIGHT_LIGHT_GREEN Ljava/lang/String; + public static final field BRIGHT_LILAC Ljava/lang/String; + public static final field BRIGHT_LIME Ljava/lang/String; + public static final field BRIGHT_LIME_GREEN Ljava/lang/String; + public static final field BRIGHT_MAGENTA Ljava/lang/String; + public static final field BRIGHT_OLIVE Ljava/lang/String; + public static final field BRIGHT_ORANGE Ljava/lang/String; + public static final field BRIGHT_PINK Ljava/lang/String; + public static final field BRIGHT_PURPLE Ljava/lang/String; + public static final field BRIGHT_RED Ljava/lang/String; + public static final field BRIGHT_SEA_GREEN Ljava/lang/String; + public static final field BRIGHT_SKY_BLUE Ljava/lang/String; + public static final field BRIGHT_TEAL Ljava/lang/String; + public static final field BRIGHT_TURQUOISE Ljava/lang/String; + public static final field BRIGHT_VIOLET Ljava/lang/String; + public static final field BRIGHT_YELLOW Ljava/lang/String; + public static final field BRIGHT_YELLOW_GREEN Ljava/lang/String; + public static final field BRITISH_RACING_GREEN Ljava/lang/String; + public static final field BRONZE Ljava/lang/String; + public static final field BROWN Ljava/lang/String; + public static final field BROWNISH Ljava/lang/String; + public static final field BROWNISH_GREEN Ljava/lang/String; + public static final field BROWNISH_GREY Ljava/lang/String; + public static final field BROWNISH_ORANGE Ljava/lang/String; + public static final field BROWNISH_PINK Ljava/lang/String; + public static final field BROWNISH_PURPLE Ljava/lang/String; + public static final field BROWNISH_RED Ljava/lang/String; + public static final field BROWNISH_YELLOW Ljava/lang/String; + public static final field BROWNY_GREEN Ljava/lang/String; + public static final field BROWNY_ORANGE Ljava/lang/String; + public static final field BROWN_GREEN Ljava/lang/String; + public static final field BROWN_GREY Ljava/lang/String; + public static final field BROWN_ORANGE Ljava/lang/String; + public static final field BROWN_RED Ljava/lang/String; + public static final field BROWN_YELLOW Ljava/lang/String; + public static final field BRUISE Ljava/lang/String; + public static final field BUBBLEGUM Ljava/lang/String; + public static final field BUBBLEGUM_PINK Ljava/lang/String; + public static final field BUBBLE_GUM_PINK Ljava/lang/String; + public static final field BUFF Ljava/lang/String; + public static final field BURGUNDY Ljava/lang/String; + public static final field BURNT_ORANGE Ljava/lang/String; + public static final field BURNT_RED Ljava/lang/String; + public static final field BURNT_SIENA Ljava/lang/String; + public static final field BURNT_SIENNA Ljava/lang/String; + public static final field BURNT_UMBER Ljava/lang/String; + public static final field BURNT_YELLOW Ljava/lang/String; + public static final field BURPLE Ljava/lang/String; + public static final field BUTTER Ljava/lang/String; + public static final field BUTTERSCOTCH Ljava/lang/String; + public static final field BUTTER_YELLOW Ljava/lang/String; + public static final field CADET_BLUE Ljava/lang/String; + public static final field CAMEL Ljava/lang/String; + public static final field CAMO Ljava/lang/String; + public static final field CAMOUFLAGE_GREEN Ljava/lang/String; + public static final field CAMO_GREEN Ljava/lang/String; + public static final field CANARY Ljava/lang/String; + public static final field CANARY_YELLOW Ljava/lang/String; + public static final field CANDY_PINK Ljava/lang/String; + public static final field CARAMEL Ljava/lang/String; + public static final field CARMINE Ljava/lang/String; + public static final field CARNATION Ljava/lang/String; + public static final field CARNATION_PINK Ljava/lang/String; + public static final field CAROLINA_BLUE Ljava/lang/String; + public static final field CELADON Ljava/lang/String; + public static final field CELERY Ljava/lang/String; + public static final field CEMENT Ljava/lang/String; + public static final field CERISE Ljava/lang/String; + public static final field CERULEAN Ljava/lang/String; + public static final field CERULEAN_BLUE Ljava/lang/String; + public static final field CHARCOAL Ljava/lang/String; + public static final field CHARCOAL_GREY Ljava/lang/String; + public static final field CHARTREUSE Ljava/lang/String; + public static final field CHERRY Ljava/lang/String; + public static final field CHERRY_RED Ljava/lang/String; + public static final field CHESTNUT Ljava/lang/String; + public static final field CHOCOLATE Ljava/lang/String; + public static final field CHOCOLATE_BROWN Ljava/lang/String; + public static final field CINNAMON Ljava/lang/String; + public static final field CLARET Ljava/lang/String; + public static final field CLAY Ljava/lang/String; + public static final field CLAY_BROWN Ljava/lang/String; + public static final field CLEAR_BLUE Ljava/lang/String; + public static final field CLOUDY_BLUE Ljava/lang/String; + public static final field COBALT Ljava/lang/String; + public static final field COBALT_BLUE Ljava/lang/String; + public static final field COCOA Ljava/lang/String; + public static final field COFFEE Ljava/lang/String; + public static final field COOL_BLUE Ljava/lang/String; + public static final field COOL_GREEN Ljava/lang/String; + public static final field COOL_GREY Ljava/lang/String; + public static final field COPPER Ljava/lang/String; + public static final field CORAL Ljava/lang/String; + public static final field CORAL_PINK Ljava/lang/String; + public static final field CORNFLOWER Ljava/lang/String; + public static final field CORNFLOWER_BLUE Ljava/lang/String; + public static final field CRANBERRY Ljava/lang/String; + public static final field CREAM Ljava/lang/String; + public static final field CREME Ljava/lang/String; + public static final field CRIMSON Ljava/lang/String; + public static final field CUSTARD Ljava/lang/String; + public static final field CYAN Ljava/lang/String; + public static final field DANDELION Ljava/lang/String; + public static final field DARK Ljava/lang/String; + public static final field DARKBLUE Ljava/lang/String; + public static final field DARKGREEN Ljava/lang/String; + public static final field DARKISH_BLUE Ljava/lang/String; + public static final field DARKISH_GREEN Ljava/lang/String; + public static final field DARKISH_PINK Ljava/lang/String; + public static final field DARKISH_PURPLE Ljava/lang/String; + public static final field DARKISH_RED Ljava/lang/String; + public static final field DARK_AQUA Ljava/lang/String; + public static final field DARK_AQUAMARINE Ljava/lang/String; + public static final field DARK_BEIGE Ljava/lang/String; + public static final field DARK_BLUE Ljava/lang/String; + public static final field DARK_BLUE_GREEN Ljava/lang/String; + public static final field DARK_BLUE_GREY Ljava/lang/String; + public static final field DARK_BROWN Ljava/lang/String; + public static final field DARK_CORAL Ljava/lang/String; + public static final field DARK_CREAM Ljava/lang/String; + public static final field DARK_CYAN Ljava/lang/String; + public static final field DARK_FOREST_GREEN Ljava/lang/String; + public static final field DARK_FUCHSIA Ljava/lang/String; + public static final field DARK_GOLD Ljava/lang/String; + public static final field DARK_GRASS_GREEN Ljava/lang/String; + public static final field DARK_GREEN Ljava/lang/String; + public static final field DARK_GREEN_BLUE Ljava/lang/String; + public static final field DARK_GREY Ljava/lang/String; + public static final field DARK_GREY_BLUE Ljava/lang/String; + public static final field DARK_HOT_PINK Ljava/lang/String; + public static final field DARK_INDIGO Ljava/lang/String; + public static final field DARK_KHAKI Ljava/lang/String; + public static final field DARK_LAVENDER Ljava/lang/String; + public static final field DARK_LILAC Ljava/lang/String; + public static final field DARK_LIME Ljava/lang/String; + public static final field DARK_LIME_GREEN Ljava/lang/String; + public static final field DARK_MAGENTA Ljava/lang/String; + public static final field DARK_MAROON Ljava/lang/String; + public static final field DARK_MAUVE Ljava/lang/String; + public static final field DARK_MINT Ljava/lang/String; + public static final field DARK_MINT_GREEN Ljava/lang/String; + public static final field DARK_MUSTARD Ljava/lang/String; + public static final field DARK_NAVY Ljava/lang/String; + public static final field DARK_NAVY_BLUE Ljava/lang/String; + public static final field DARK_OLIVE Ljava/lang/String; + public static final field DARK_OLIVE_GREEN Ljava/lang/String; + public static final field DARK_ORANGE Ljava/lang/String; + public static final field DARK_PASTEL_GREEN Ljava/lang/String; + public static final field DARK_PEACH Ljava/lang/String; + public static final field DARK_PERIWINKLE Ljava/lang/String; + public static final field DARK_PINK Ljava/lang/String; + public static final field DARK_PLUM Ljava/lang/String; + public static final field DARK_PURPLE Ljava/lang/String; + public static final field DARK_RED Ljava/lang/String; + public static final field DARK_ROSE Ljava/lang/String; + public static final field DARK_ROYAL_BLUE Ljava/lang/String; + public static final field DARK_SAGE Ljava/lang/String; + public static final field DARK_SALMON Ljava/lang/String; + public static final field DARK_SAND Ljava/lang/String; + public static final field DARK_SEAFOAM Ljava/lang/String; + public static final field DARK_SEAFOAM_GREEN Ljava/lang/String; + public static final field DARK_SEA_GREEN Ljava/lang/String; + public static final field DARK_SKY_BLUE Ljava/lang/String; + public static final field DARK_SLATE_BLUE Ljava/lang/String; + public static final field DARK_TAN Ljava/lang/String; + public static final field DARK_TAUPE Ljava/lang/String; + public static final field DARK_TEAL Ljava/lang/String; + public static final field DARK_TURQUOISE Ljava/lang/String; + public static final field DARK_VIOLET Ljava/lang/String; + public static final field DARK_YELLOW Ljava/lang/String; + public static final field DARK_YELLOW_GREEN Ljava/lang/String; + public static final field DEEP_AQUA Ljava/lang/String; + public static final field DEEP_BLUE Ljava/lang/String; + public static final field DEEP_BROWN Ljava/lang/String; + public static final field DEEP_GREEN Ljava/lang/String; + public static final field DEEP_LAVENDER Ljava/lang/String; + public static final field DEEP_LILAC Ljava/lang/String; + public static final field DEEP_MAGENTA Ljava/lang/String; + public static final field DEEP_ORANGE Ljava/lang/String; + public static final field DEEP_PINK Ljava/lang/String; + public static final field DEEP_PURPLE Ljava/lang/String; + public static final field DEEP_RED Ljava/lang/String; + public static final field DEEP_ROSE Ljava/lang/String; + public static final field DEEP_SEA_BLUE Ljava/lang/String; + public static final field DEEP_SKY_BLUE Ljava/lang/String; + public static final field DEEP_TEAL Ljava/lang/String; + public static final field DEEP_TURQUOISE Ljava/lang/String; + public static final field DEEP_VIOLET Ljava/lang/String; + public static final field DENIM Ljava/lang/String; + public static final field DENIM_BLUE Ljava/lang/String; + public static final field DESERT Ljava/lang/String; + public static final field DIARRHEA Ljava/lang/String; + public static final field DIRT Ljava/lang/String; + public static final field DIRTY_BLUE Ljava/lang/String; + public static final field DIRTY_GREEN Ljava/lang/String; + public static final field DIRTY_ORANGE Ljava/lang/String; + public static final field DIRTY_PINK Ljava/lang/String; + public static final field DIRTY_PURPLE Ljava/lang/String; + public static final field DIRTY_YELLOW Ljava/lang/String; + public static final field DIRT_BROWN Ljava/lang/String; + public static final field DODGER_BLUE Ljava/lang/String; + public static final field DRAB Ljava/lang/String; + public static final field DRAB_GREEN Ljava/lang/String; + public static final field DRIED_BLOOD Ljava/lang/String; + public static final field DUCK_EGG_BLUE Ljava/lang/String; + public static final field DULL_BLUE Ljava/lang/String; + public static final field DULL_BROWN Ljava/lang/String; + public static final field DULL_GREEN Ljava/lang/String; + public static final field DULL_ORANGE Ljava/lang/String; + public static final field DULL_PINK Ljava/lang/String; + public static final field DULL_PURPLE Ljava/lang/String; + public static final field DULL_RED Ljava/lang/String; + public static final field DULL_TEAL Ljava/lang/String; + public static final field DULL_YELLOW Ljava/lang/String; + public static final field DUSK Ljava/lang/String; + public static final field DUSKY_BLUE Ljava/lang/String; + public static final field DUSKY_PINK Ljava/lang/String; + public static final field DUSKY_PURPLE Ljava/lang/String; + public static final field DUSKY_ROSE Ljava/lang/String; + public static final field DUSK_BLUE Ljava/lang/String; + public static final field DUST Ljava/lang/String; + public static final field DUSTY_BLUE Ljava/lang/String; + public static final field DUSTY_GREEN Ljava/lang/String; + public static final field DUSTY_LAVENDER Ljava/lang/String; + public static final field DUSTY_ORANGE Ljava/lang/String; + public static final field DUSTY_PINK Ljava/lang/String; + public static final field DUSTY_PURPLE Ljava/lang/String; + public static final field DUSTY_RED Ljava/lang/String; + public static final field DUSTY_ROSE Ljava/lang/String; + public static final field DUSTY_TEAL Ljava/lang/String; + public static final field EARTH Ljava/lang/String; + public static final field EASTER_GREEN Ljava/lang/String; + public static final field EASTER_PURPLE Ljava/lang/String; + public static final field ECRU Ljava/lang/String; + public static final field EGGPLANT Ljava/lang/String; + public static final field EGGPLANT_PURPLE Ljava/lang/String; + public static final field EGGSHELL Ljava/lang/String; + public static final field EGGSHELL_BLUE Ljava/lang/String; + public static final field EGG_SHELL Ljava/lang/String; + public static final field ELECTRIC_BLUE Ljava/lang/String; + public static final field ELECTRIC_GREEN Ljava/lang/String; + public static final field ELECTRIC_LIME Ljava/lang/String; + public static final field ELECTRIC_PINK Ljava/lang/String; + public static final field ELECTRIC_PURPLE Ljava/lang/String; + public static final field EMERALD Ljava/lang/String; + public static final field EMERALD_GREEN Ljava/lang/String; + public static final field EVERGREEN Ljava/lang/String; + public static final field FADED_BLUE Ljava/lang/String; + public static final field FADED_GREEN Ljava/lang/String; + public static final field FADED_ORANGE Ljava/lang/String; + public static final field FADED_PINK Ljava/lang/String; + public static final field FADED_PURPLE Ljava/lang/String; + public static final field FADED_RED Ljava/lang/String; + public static final field FADED_YELLOW Ljava/lang/String; + public static final field FAWN Ljava/lang/String; + public static final field FERN Ljava/lang/String; + public static final field FERN_GREEN Ljava/lang/String; + public static final field FIRE_ENGINE_RED Ljava/lang/String; + public static final field FLAT_BLUE Ljava/lang/String; + public static final field FLAT_GREEN Ljava/lang/String; + public static final field FLUORESCENT_GREEN Ljava/lang/String; + public static final field FLURO_GREEN Ljava/lang/String; + public static final field FOAM_GREEN Ljava/lang/String; + public static final field FOREST Ljava/lang/String; + public static final field FOREST_GREEN Ljava/lang/String; + public static final field FORREST_GREEN Ljava/lang/String; + public static final field FRENCH_BLUE Ljava/lang/String; + public static final field FRESH_GREEN Ljava/lang/String; + public static final field FROG_GREEN Ljava/lang/String; + public static final field FUCHSIA Ljava/lang/String; + public static final field GOLD Ljava/lang/String; + public static final field GOLDEN Ljava/lang/String; + public static final field GOLDENROD Ljava/lang/String; + public static final field GOLDEN_BROWN Ljava/lang/String; + public static final field GOLDEN_ROD Ljava/lang/String; + public static final field GOLDEN_YELLOW Ljava/lang/String; + public static final field GRAPE Ljava/lang/String; + public static final field GRAPEFRUIT Ljava/lang/String; + public static final field GRAPE_PURPLE Ljava/lang/String; + public static final field GRASS Ljava/lang/String; + public static final field GRASSY_GREEN Ljava/lang/String; + public static final field GRASS_GREEN Ljava/lang/String; + public static final field GREEN Ljava/lang/String; + public static final field GREENBLUE Ljava/lang/String; + public static final field GREENISH Ljava/lang/String; + public static final field GREENISH_BEIGE Ljava/lang/String; + public static final field GREENISH_BLUE Ljava/lang/String; + public static final field GREENISH_BROWN Ljava/lang/String; + public static final field GREENISH_CYAN Ljava/lang/String; + public static final field GREENISH_GREY Ljava/lang/String; + public static final field GREENISH_TAN Ljava/lang/String; + public static final field GREENISH_TEAL Ljava/lang/String; + public static final field GREENISH_TURQUOISE Ljava/lang/String; + public static final field GREENISH_YELLOW Ljava/lang/String; + public static final field GREENY_BLUE Ljava/lang/String; + public static final field GREENY_BROWN Ljava/lang/String; + public static final field GREENY_GREY Ljava/lang/String; + public static final field GREENY_YELLOW Ljava/lang/String; + public static final field GREEN_APPLE Ljava/lang/String; + public static final field GREEN_BLUE Ljava/lang/String; + public static final field GREEN_BROWN Ljava/lang/String; + public static final field GREEN_GREY Ljava/lang/String; + public static final field GREEN_TEAL Ljava/lang/String; + public static final field GREEN_YELLOW Ljava/lang/String; + public static final field GREY Ljava/lang/String; + public static final field GREYBLUE Ljava/lang/String; + public static final field GREYISH Ljava/lang/String; + public static final field GREYISH_BLUE Ljava/lang/String; + public static final field GREYISH_BROWN Ljava/lang/String; + public static final field GREYISH_GREEN Ljava/lang/String; + public static final field GREYISH_PINK Ljava/lang/String; + public static final field GREYISH_PURPLE Ljava/lang/String; + public static final field GREYISH_TEAL Ljava/lang/String; + public static final field GREY_BLUE Ljava/lang/String; + public static final field GREY_BROWN Ljava/lang/String; + public static final field GREY_GREEN Ljava/lang/String; + public static final field GREY_PINK Ljava/lang/String; + public static final field GREY_PURPLE Ljava/lang/String; + public static final field GREY_TEAL Ljava/lang/String; + public static final field GROSS_GREEN Ljava/lang/String; + public static final field GUNMETAL Ljava/lang/String; + public static final field HAZEL Ljava/lang/String; + public static final field HEATHER Ljava/lang/String; + public static final field HELIOTROPE Ljava/lang/String; + public static final field HIGHLIGHTER_GREEN Ljava/lang/String; + public static final field HOSPITAL_GREEN Ljava/lang/String; + public static final field HOT_GREEN Ljava/lang/String; + public static final field HOT_MAGENTA Ljava/lang/String; + public static final field HOT_PINK Ljava/lang/String; + public static final field HOT_PURPLE Ljava/lang/String; + public static final field HUNTER_GREEN Ljava/lang/String; + public static final field ICE Ljava/lang/String; + public static final field ICE_BLUE Ljava/lang/String; + public static final field ICKY_GREEN Ljava/lang/String; + public static final field INDIAN_RED Ljava/lang/String; + public static final field INDIGO Ljava/lang/String; + public static final field INDIGO_BLUE Ljava/lang/String; + public static final field INSTANCE Lspace/kscience/plotly/palettes/Xkcd; + public static final field IRIS Ljava/lang/String; + public static final field IRISH_GREEN Ljava/lang/String; + public static final field IVORY Ljava/lang/String; + public static final field JADE Ljava/lang/String; + public static final field JADE_GREEN Ljava/lang/String; + public static final field JUNGLE_GREEN Ljava/lang/String; + public static final field KELLEY_GREEN Ljava/lang/String; + public static final field KELLY_GREEN Ljava/lang/String; + public static final field KERMIT_GREEN Ljava/lang/String; + public static final field KEY_LIME Ljava/lang/String; + public static final field KHAKI Ljava/lang/String; + public static final field KHAKI_GREEN Ljava/lang/String; + public static final field KIWI Ljava/lang/String; + public static final field KIWI_GREEN Ljava/lang/String; + public static final field LAVENDER Ljava/lang/String; + public static final field LAVENDER_BLUE Ljava/lang/String; + public static final field LAVENDER_PINK Ljava/lang/String; + public static final field LAWN_GREEN Ljava/lang/String; + public static final field LEAF Ljava/lang/String; + public static final field LEAFY_GREEN Ljava/lang/String; + public static final field LEAF_GREEN Ljava/lang/String; + public static final field LEATHER Ljava/lang/String; + public static final field LEMON Ljava/lang/String; + public static final field LEMON_GREEN Ljava/lang/String; + public static final field LEMON_LIME Ljava/lang/String; + public static final field LEMON_YELLOW Ljava/lang/String; + public static final field LICHEN Ljava/lang/String; + public static final field LIGHTBLUE Ljava/lang/String; + public static final field LIGHTER_GREEN Ljava/lang/String; + public static final field LIGHTER_PURPLE Ljava/lang/String; + public static final field LIGHTGREEN Ljava/lang/String; + public static final field LIGHTISH_BLUE Ljava/lang/String; + public static final field LIGHTISH_GREEN Ljava/lang/String; + public static final field LIGHTISH_PURPLE Ljava/lang/String; + public static final field LIGHTISH_RED Ljava/lang/String; + public static final field LIGHT_AQUA Ljava/lang/String; + public static final field LIGHT_AQUAMARINE Ljava/lang/String; + public static final field LIGHT_BEIGE Ljava/lang/String; + public static final field LIGHT_BLUE Ljava/lang/String; + public static final field LIGHT_BLUE_GREEN Ljava/lang/String; + public static final field LIGHT_BLUE_GREY Ljava/lang/String; + public static final field LIGHT_BLUISH_GREEN Ljava/lang/String; + public static final field LIGHT_BRIGHT_GREEN Ljava/lang/String; + public static final field LIGHT_BROWN Ljava/lang/String; + public static final field LIGHT_BURGUNDY Ljava/lang/String; + public static final field LIGHT_CYAN Ljava/lang/String; + public static final field LIGHT_EGGPLANT Ljava/lang/String; + public static final field LIGHT_FOREST_GREEN Ljava/lang/String; + public static final field LIGHT_GOLD Ljava/lang/String; + public static final field LIGHT_GRASS_GREEN Ljava/lang/String; + public static final field LIGHT_GREEN Ljava/lang/String; + public static final field LIGHT_GREENISH_BLUE Ljava/lang/String; + public static final field LIGHT_GREEN_BLUE Ljava/lang/String; + public static final field LIGHT_GREY Ljava/lang/String; + public static final field LIGHT_GREY_BLUE Ljava/lang/String; + public static final field LIGHT_GREY_GREEN Ljava/lang/String; + public static final field LIGHT_INDIGO Ljava/lang/String; + public static final field LIGHT_KHAKI Ljava/lang/String; + public static final field LIGHT_LAVENDAR Ljava/lang/String; + public static final field LIGHT_LAVENDER Ljava/lang/String; + public static final field LIGHT_LIGHT_BLUE Ljava/lang/String; + public static final field LIGHT_LIGHT_GREEN Ljava/lang/String; + public static final field LIGHT_LILAC Ljava/lang/String; + public static final field LIGHT_LIME Ljava/lang/String; + public static final field LIGHT_LIME_GREEN Ljava/lang/String; + public static final field LIGHT_MAGENTA Ljava/lang/String; + public static final field LIGHT_MAROON Ljava/lang/String; + public static final field LIGHT_MAUVE Ljava/lang/String; + public static final field LIGHT_MINT Ljava/lang/String; + public static final field LIGHT_MINT_GREEN Ljava/lang/String; + public static final field LIGHT_MOSS_GREEN Ljava/lang/String; + public static final field LIGHT_MUSTARD Ljava/lang/String; + public static final field LIGHT_NAVY Ljava/lang/String; + public static final field LIGHT_NAVY_BLUE Ljava/lang/String; + public static final field LIGHT_NEON_GREEN Ljava/lang/String; + public static final field LIGHT_OLIVE Ljava/lang/String; + public static final field LIGHT_OLIVE_GREEN Ljava/lang/String; + public static final field LIGHT_ORANGE Ljava/lang/String; + public static final field LIGHT_PASTEL_GREEN Ljava/lang/String; + public static final field LIGHT_PEACH Ljava/lang/String; + public static final field LIGHT_PEA_GREEN Ljava/lang/String; + public static final field LIGHT_PERIWINKLE Ljava/lang/String; + public static final field LIGHT_PINK Ljava/lang/String; + public static final field LIGHT_PLUM Ljava/lang/String; + public static final field LIGHT_PURPLE Ljava/lang/String; + public static final field LIGHT_RED Ljava/lang/String; + public static final field LIGHT_ROSE Ljava/lang/String; + public static final field LIGHT_ROYAL_BLUE Ljava/lang/String; + public static final field LIGHT_SAGE Ljava/lang/String; + public static final field LIGHT_SALMON Ljava/lang/String; + public static final field LIGHT_SEAFOAM Ljava/lang/String; + public static final field LIGHT_SEAFOAM_GREEN Ljava/lang/String; + public static final field LIGHT_SEA_GREEN Ljava/lang/String; + public static final field LIGHT_SKY_BLUE Ljava/lang/String; + public static final field LIGHT_TAN Ljava/lang/String; + public static final field LIGHT_TEAL Ljava/lang/String; + public static final field LIGHT_TURQUOISE Ljava/lang/String; + public static final field LIGHT_URPLE Ljava/lang/String; + public static final field LIGHT_VIOLET Ljava/lang/String; + public static final field LIGHT_YELLOW Ljava/lang/String; + public static final field LIGHT_YELLOWISH_GREEN Ljava/lang/String; + public static final field LIGHT_YELLOW_GREEN Ljava/lang/String; + public static final field LILAC Ljava/lang/String; + public static final field LILIAC Ljava/lang/String; + public static final field LIME Ljava/lang/String; + public static final field LIME_GREEN Ljava/lang/String; + public static final field LIME_YELLOW Ljava/lang/String; + public static final field LIPSTICK Ljava/lang/String; + public static final field LIPSTICK_RED Ljava/lang/String; + public static final field MACARONI_AND_CHEESE Ljava/lang/String; + public static final field MAGENTA Ljava/lang/String; + public static final field MAHOGANY Ljava/lang/String; + public static final field MAIZE Ljava/lang/String; + public static final field MANGO Ljava/lang/String; + public static final field MANILLA Ljava/lang/String; + public static final field MARIGOLD Ljava/lang/String; + public static final field MARINE Ljava/lang/String; + public static final field MARINE_BLUE Ljava/lang/String; + public static final field MAROON Ljava/lang/String; + public static final field MAUVE Ljava/lang/String; + public static final field MEDIUM_BLUE Ljava/lang/String; + public static final field MEDIUM_BROWN Ljava/lang/String; + public static final field MEDIUM_GREEN Ljava/lang/String; + public static final field MEDIUM_GREY Ljava/lang/String; + public static final field MEDIUM_PINK Ljava/lang/String; + public static final field MEDIUM_PURPLE Ljava/lang/String; + public static final field MELON Ljava/lang/String; + public static final field MERLOT Ljava/lang/String; + public static final field METALLIC_BLUE Ljava/lang/String; + public static final field MIDNIGHT Ljava/lang/String; + public static final field MIDNIGHT_BLUE Ljava/lang/String; + public static final field MIDNIGHT_PURPLE Ljava/lang/String; + public static final field MID_BLUE Ljava/lang/String; + public static final field MID_GREEN Ljava/lang/String; + public static final field MILITARY_GREEN Ljava/lang/String; + public static final field MILK_CHOCOLATE Ljava/lang/String; + public static final field MINT Ljava/lang/String; + public static final field MINTY_GREEN Ljava/lang/String; + public static final field MINT_GREEN Ljava/lang/String; + public static final field MOCHA Ljava/lang/String; + public static final field MOSS Ljava/lang/String; + public static final field MOSSY_GREEN Ljava/lang/String; + public static final field MOSS_GREEN Ljava/lang/String; + public static final field MUD Ljava/lang/String; + public static final field MUDDY_BROWN Ljava/lang/String; + public static final field MUDDY_GREEN Ljava/lang/String; + public static final field MUDDY_YELLOW Ljava/lang/String; + public static final field MUD_BROWN Ljava/lang/String; + public static final field MUD_GREEN Ljava/lang/String; + public static final field MULBERRY Ljava/lang/String; + public static final field MURKY_GREEN Ljava/lang/String; + public static final field MUSHROOM Ljava/lang/String; + public static final field MUSTARD Ljava/lang/String; + public static final field MUSTARD_BROWN Ljava/lang/String; + public static final field MUSTARD_GREEN Ljava/lang/String; + public static final field MUSTARD_YELLOW Ljava/lang/String; + public static final field MUTED_BLUE Ljava/lang/String; + public static final field MUTED_GREEN Ljava/lang/String; + public static final field MUTED_PINK Ljava/lang/String; + public static final field MUTED_PURPLE Ljava/lang/String; + public static final field NASTY_GREEN Ljava/lang/String; + public static final field NAVY Ljava/lang/String; + public static final field NAVY_BLUE Ljava/lang/String; + public static final field NAVY_GREEN Ljava/lang/String; + public static final field NEON_BLUE Ljava/lang/String; + public static final field NEON_GREEN Ljava/lang/String; + public static final field NEON_PINK Ljava/lang/String; + public static final field NEON_PURPLE Ljava/lang/String; + public static final field NEON_RED Ljava/lang/String; + public static final field NEON_YELLOW Ljava/lang/String; + public static final field NICE_BLUE Ljava/lang/String; + public static final field NIGHT_BLUE Ljava/lang/String; + public static final field OCEAN Ljava/lang/String; + public static final field OCEAN_BLUE Ljava/lang/String; + public static final field OCEAN_GREEN Ljava/lang/String; + public static final field OCHER Ljava/lang/String; + public static final field OCHRE Ljava/lang/String; + public static final field OCRE Ljava/lang/String; + public static final field OFF_BLUE Ljava/lang/String; + public static final field OFF_GREEN Ljava/lang/String; + public static final field OFF_WHITE Ljava/lang/String; + public static final field OFF_YELLOW Ljava/lang/String; + public static final field OLD_PINK Ljava/lang/String; + public static final field OLD_ROSE Ljava/lang/String; + public static final field OLIVE Ljava/lang/String; + public static final field OLIVE_BROWN Ljava/lang/String; + public static final field OLIVE_DRAB Ljava/lang/String; + public static final field OLIVE_GREEN Ljava/lang/String; + public static final field OLIVE_YELLOW Ljava/lang/String; + public static final field ORANGE Ljava/lang/String; + public static final field ORANGEISH Ljava/lang/String; + public static final field ORANGERED Ljava/lang/String; + public static final field ORANGEY_BROWN Ljava/lang/String; + public static final field ORANGEY_RED Ljava/lang/String; + public static final field ORANGEY_YELLOW Ljava/lang/String; + public static final field ORANGE_BROWN Ljava/lang/String; + public static final field ORANGE_PINK Ljava/lang/String; + public static final field ORANGE_RED Ljava/lang/String; + public static final field ORANGE_YELLOW Ljava/lang/String; + public static final field ORANGISH Ljava/lang/String; + public static final field ORANGISH_BROWN Ljava/lang/String; + public static final field ORANGISH_RED Ljava/lang/String; + public static final field ORCHID Ljava/lang/String; + public static final field PALE Ljava/lang/String; + public static final field PALE_AQUA Ljava/lang/String; + public static final field PALE_BLUE Ljava/lang/String; + public static final field PALE_BROWN Ljava/lang/String; + public static final field PALE_CYAN Ljava/lang/String; + public static final field PALE_GOLD Ljava/lang/String; + public static final field PALE_GREEN Ljava/lang/String; + public static final field PALE_GREY Ljava/lang/String; + public static final field PALE_LAVENDER Ljava/lang/String; + public static final field PALE_LIGHT_GREEN Ljava/lang/String; + public static final field PALE_LILAC Ljava/lang/String; + public static final field PALE_LIME Ljava/lang/String; + public static final field PALE_LIME_GREEN Ljava/lang/String; + public static final field PALE_MAGENTA Ljava/lang/String; + public static final field PALE_MAUVE Ljava/lang/String; + public static final field PALE_OLIVE Ljava/lang/String; + public static final field PALE_OLIVE_GREEN Ljava/lang/String; + public static final field PALE_ORANGE Ljava/lang/String; + public static final field PALE_PEACH Ljava/lang/String; + public static final field PALE_PINK Ljava/lang/String; + public static final field PALE_PURPLE Ljava/lang/String; + public static final field PALE_RED Ljava/lang/String; + public static final field PALE_ROSE Ljava/lang/String; + public static final field PALE_SALMON Ljava/lang/String; + public static final field PALE_SKY_BLUE Ljava/lang/String; + public static final field PALE_TEAL Ljava/lang/String; + public static final field PALE_TURQUOISE Ljava/lang/String; + public static final field PALE_VIOLET Ljava/lang/String; + public static final field PALE_YELLOW Ljava/lang/String; + public static final field PARCHMENT Ljava/lang/String; + public static final field PASTEL_BLUE Ljava/lang/String; + public static final field PASTEL_GREEN Ljava/lang/String; + public static final field PASTEL_ORANGE Ljava/lang/String; + public static final field PASTEL_PINK Ljava/lang/String; + public static final field PASTEL_PURPLE Ljava/lang/String; + public static final field PASTEL_RED Ljava/lang/String; + public static final field PASTEL_YELLOW Ljava/lang/String; + public static final field PEA Ljava/lang/String; + public static final field PEACH Ljava/lang/String; + public static final field PEACHY_PINK Ljava/lang/String; + public static final field PEACOCK_BLUE Ljava/lang/String; + public static final field PEAR Ljava/lang/String; + public static final field PEA_GREEN Ljava/lang/String; + public static final field PEA_SOUP Ljava/lang/String; + public static final field PEA_SOUP_GREEN Ljava/lang/String; + public static final field PERIWINKLE Ljava/lang/String; + public static final field PERIWINKLE_BLUE Ljava/lang/String; + public static final field PERRYWINKLE Ljava/lang/String; + public static final field PETROL Ljava/lang/String; + public static final field PIG_PINK Ljava/lang/String; + public static final field PINE Ljava/lang/String; + public static final field PINE_GREEN Ljava/lang/String; + public static final field PINK Ljava/lang/String; + public static final field PINKISH Ljava/lang/String; + public static final field PINKISH_BROWN Ljava/lang/String; + public static final field PINKISH_GREY Ljava/lang/String; + public static final field PINKISH_ORANGE Ljava/lang/String; + public static final field PINKISH_PURPLE Ljava/lang/String; + public static final field PINKISH_RED Ljava/lang/String; + public static final field PINKISH_TAN Ljava/lang/String; + public static final field PINKY Ljava/lang/String; + public static final field PINKY_PURPLE Ljava/lang/String; + public static final field PINKY_RED Ljava/lang/String; + public static final field PINK_PURPLE Ljava/lang/String; + public static final field PINK_RED Ljava/lang/String; + public static final field PISS_YELLOW Ljava/lang/String; + public static final field PISTACHIO Ljava/lang/String; + public static final field PLUM Ljava/lang/String; + public static final field PLUM_PURPLE Ljava/lang/String; + public static final field POISON_GREEN Ljava/lang/String; + public static final field POO Ljava/lang/String; + public static final field POOP Ljava/lang/String; + public static final field POOP_BROWN Ljava/lang/String; + public static final field POOP_GREEN Ljava/lang/String; + public static final field POO_BROWN Ljava/lang/String; + public static final field POWDER_BLUE Ljava/lang/String; + public static final field POWDER_PINK Ljava/lang/String; + public static final field PRIMARY_BLUE Ljava/lang/String; + public static final field PRUSSIAN_BLUE Ljava/lang/String; + public static final field PUCE Ljava/lang/String; + public static final field PUKE Ljava/lang/String; + public static final field PUKE_BROWN Ljava/lang/String; + public static final field PUKE_GREEN Ljava/lang/String; + public static final field PUKE_YELLOW Ljava/lang/String; + public static final field PUMPKIN Ljava/lang/String; + public static final field PUMPKIN_ORANGE Ljava/lang/String; + public static final field PURE_BLUE Ljava/lang/String; + public static final field PURPLE Ljava/lang/String; + public static final field PURPLEISH Ljava/lang/String; + public static final field PURPLEISH_BLUE Ljava/lang/String; + public static final field PURPLEISH_PINK Ljava/lang/String; + public static final field PURPLEY Ljava/lang/String; + public static final field PURPLEY_BLUE Ljava/lang/String; + public static final field PURPLEY_GREY Ljava/lang/String; + public static final field PURPLEY_PINK Ljava/lang/String; + public static final field PURPLE_BLUE Ljava/lang/String; + public static final field PURPLE_BROWN Ljava/lang/String; + public static final field PURPLE_GREY Ljava/lang/String; + public static final field PURPLE_PINK Ljava/lang/String; + public static final field PURPLE_RED Ljava/lang/String; + public static final field PURPLISH Ljava/lang/String; + public static final field PURPLISH_BLUE Ljava/lang/String; + public static final field PURPLISH_BROWN Ljava/lang/String; + public static final field PURPLISH_GREY Ljava/lang/String; + public static final field PURPLISH_PINK Ljava/lang/String; + public static final field PURPLISH_RED Ljava/lang/String; + public static final field PURPLY Ljava/lang/String; + public static final field PURPLY_BLUE Ljava/lang/String; + public static final field PURPLY_PINK Ljava/lang/String; + public static final field PUTTY Ljava/lang/String; + public static final field RACING_GREEN Ljava/lang/String; + public static final field RADIOACTIVE_GREEN Ljava/lang/String; + public static final field RASPBERRY Ljava/lang/String; + public static final field RAW_SIENNA Ljava/lang/String; + public static final field RAW_UMBER Ljava/lang/String; + public static final field REALLY_LIGHT_BLUE Ljava/lang/String; + public static final field RED Ljava/lang/String; + public static final field REDDISH Ljava/lang/String; + public static final field REDDISH_BROWN Ljava/lang/String; + public static final field REDDISH_GREY Ljava/lang/String; + public static final field REDDISH_ORANGE Ljava/lang/String; + public static final field REDDISH_PINK Ljava/lang/String; + public static final field REDDISH_PURPLE Ljava/lang/String; + public static final field REDDY_BROWN Ljava/lang/String; + public static final field RED_BROWN Ljava/lang/String; + public static final field RED_ORANGE Ljava/lang/String; + public static final field RED_PINK Ljava/lang/String; + public static final field RED_PURPLE Ljava/lang/String; + public static final field RED_VIOLET Ljava/lang/String; + public static final field RED_WINE Ljava/lang/String; + public static final field RICH_BLUE Ljava/lang/String; + public static final field RICH_PURPLE Ljava/lang/String; + public static final field ROBIN_EGG_BLUE Ljava/lang/String; + public static final field ROSA Ljava/lang/String; + public static final field ROSE Ljava/lang/String; + public static final field ROSE_PINK Ljava/lang/String; + public static final field ROSE_RED Ljava/lang/String; + public static final field ROSY_PINK Ljava/lang/String; + public static final field ROUGE Ljava/lang/String; + public static final field ROYAL Ljava/lang/String; + public static final field ROYAL_BLUE Ljava/lang/String; + public static final field ROYAL_PURPLE Ljava/lang/String; + public static final field RUBY Ljava/lang/String; + public static final field RUSSET Ljava/lang/String; + public static final field RUST Ljava/lang/String; + public static final field RUSTY_ORANGE Ljava/lang/String; + public static final field RUSTY_RED Ljava/lang/String; + public static final field RUST_BROWN Ljava/lang/String; + public static final field RUST_ORANGE Ljava/lang/String; + public static final field RUST_RED Ljava/lang/String; + public static final field SAFFRON Ljava/lang/String; + public static final field SAGE Ljava/lang/String; + public static final field SAGE_GREEN Ljava/lang/String; + public static final field SALMON Ljava/lang/String; + public static final field SALMON_PINK Ljava/lang/String; + public static final field SAND Ljava/lang/String; + public static final field SANDSTONE Ljava/lang/String; + public static final field SANDY Ljava/lang/String; + public static final field SANDY_BROWN Ljava/lang/String; + public static final field SANDY_YELLOW Ljava/lang/String; + public static final field SAND_BROWN Ljava/lang/String; + public static final field SAND_YELLOW Ljava/lang/String; + public static final field SAPPHIRE Ljava/lang/String; + public static final field SAP_GREEN Ljava/lang/String; + public static final field SCARLET Ljava/lang/String; + public static final field SEA Ljava/lang/String; + public static final field SEAFOAM Ljava/lang/String; + public static final field SEAFOAM_BLUE Ljava/lang/String; + public static final field SEAFOAM_GREEN Ljava/lang/String; + public static final field SEAWEED Ljava/lang/String; + public static final field SEAWEED_GREEN Ljava/lang/String; + public static final field SEA_BLUE Ljava/lang/String; + public static final field SEA_GREEN Ljava/lang/String; + public static final field SEPIA Ljava/lang/String; + public static final field SHAMROCK Ljava/lang/String; + public static final field SHAMROCK_GREEN Ljava/lang/String; + public static final field SHIT Ljava/lang/String; + public static final field SHIT_BROWN Ljava/lang/String; + public static final field SHIT_GREEN Ljava/lang/String; + public static final field SHOCKING_PINK Ljava/lang/String; + public static final field SICKLY_GREEN Ljava/lang/String; + public static final field SICKLY_YELLOW Ljava/lang/String; + public static final field SICK_GREEN Ljava/lang/String; + public static final field SIENNA Ljava/lang/String; + public static final field SILVER Ljava/lang/String; + public static final field SKY Ljava/lang/String; + public static final field SKY_BLUE Ljava/lang/String; + public static final field SLATE Ljava/lang/String; + public static final field SLATE_BLUE Ljava/lang/String; + public static final field SLATE_GREEN Ljava/lang/String; + public static final field SLATE_GREY Ljava/lang/String; + public static final field SLIME_GREEN Ljava/lang/String; + public static final field SNOT Ljava/lang/String; + public static final field SNOT_GREEN Ljava/lang/String; + public static final field SOFT_BLUE Ljava/lang/String; + public static final field SOFT_GREEN Ljava/lang/String; + public static final field SOFT_PINK Ljava/lang/String; + public static final field SOFT_PURPLE Ljava/lang/String; + public static final field SPEARMINT Ljava/lang/String; + public static final field SPRING_GREEN Ljava/lang/String; + public static final field SPRUCE Ljava/lang/String; + public static final field SQUASH Ljava/lang/String; + public static final field STEEL Ljava/lang/String; + public static final field STEEL_BLUE Ljava/lang/String; + public static final field STEEL_GREY Ljava/lang/String; + public static final field STONE Ljava/lang/String; + public static final field STORMY_BLUE Ljava/lang/String; + public static final field STRAW Ljava/lang/String; + public static final field STRAWBERRY Ljava/lang/String; + public static final field STRONG_BLUE Ljava/lang/String; + public static final field STRONG_PINK Ljava/lang/String; + public static final field SUNFLOWER Ljava/lang/String; + public static final field SUNFLOWER_YELLOW Ljava/lang/String; + public static final field SUNNY_YELLOW Ljava/lang/String; + public static final field SUNSHINE_YELLOW Ljava/lang/String; + public static final field SUN_YELLOW Ljava/lang/String; + public static final field SWAMP Ljava/lang/String; + public static final field SWAMP_GREEN Ljava/lang/String; + public static final field TAN Ljava/lang/String; + public static final field TANGERINE Ljava/lang/String; + public static final field TAN_BROWN Ljava/lang/String; + public static final field TAN_GREEN Ljava/lang/String; + public static final field TAUPE Ljava/lang/String; + public static final field TEA Ljava/lang/String; + public static final field TEAL Ljava/lang/String; + public static final field TEALISH Ljava/lang/String; + public static final field TEALISH_GREEN Ljava/lang/String; + public static final field TEAL_BLUE Ljava/lang/String; + public static final field TEAL_GREEN Ljava/lang/String; + public static final field TEA_GREEN Ljava/lang/String; + public static final field TERRACOTA Ljava/lang/String; + public static final field TERRACOTTA Ljava/lang/String; + public static final field TERRA_COTTA Ljava/lang/String; + public static final field TIFFANY_BLUE Ljava/lang/String; + public static final field TOMATO Ljava/lang/String; + public static final field TOMATO_RED Ljava/lang/String; + public static final field TOPAZ Ljava/lang/String; + public static final field TOUPE Ljava/lang/String; + public static final field TOXIC_GREEN Ljava/lang/String; + public static final field TREE_GREEN Ljava/lang/String; + public static final field TRUE_BLUE Ljava/lang/String; + public static final field TRUE_GREEN Ljava/lang/String; + public static final field TURQUOISE Ljava/lang/String; + public static final field TURQUOISE_BLUE Ljava/lang/String; + public static final field TURQUOISE_GREEN Ljava/lang/String; + public static final field TURTLE_GREEN Ljava/lang/String; + public static final field TWILIGHT Ljava/lang/String; + public static final field TWILIGHT_BLUE Ljava/lang/String; + public static final field UGLY_BLUE Ljava/lang/String; + public static final field UGLY_BROWN Ljava/lang/String; + public static final field UGLY_GREEN Ljava/lang/String; + public static final field UGLY_PINK Ljava/lang/String; + public static final field UGLY_PURPLE Ljava/lang/String; + public static final field UGLY_YELLOW Ljava/lang/String; + public static final field ULTRAMARINE Ljava/lang/String; + public static final field ULTRAMARINE_BLUE Ljava/lang/String; + public static final field UMBER Ljava/lang/String; + public static final field VELVET Ljava/lang/String; + public static final field VERMILLION Ljava/lang/String; + public static final field VERY_DARK_BLUE Ljava/lang/String; + public static final field VERY_DARK_BROWN Ljava/lang/String; + public static final field VERY_DARK_GREEN Ljava/lang/String; + public static final field VERY_DARK_PURPLE Ljava/lang/String; + public static final field VERY_LIGHT_BLUE Ljava/lang/String; + public static final field VERY_LIGHT_BROWN Ljava/lang/String; + public static final field VERY_LIGHT_GREEN Ljava/lang/String; + public static final field VERY_LIGHT_PINK Ljava/lang/String; + public static final field VERY_LIGHT_PURPLE Ljava/lang/String; + public static final field VERY_PALE_BLUE Ljava/lang/String; + public static final field VERY_PALE_GREEN Ljava/lang/String; + public static final field VIBRANT_BLUE Ljava/lang/String; + public static final field VIBRANT_GREEN Ljava/lang/String; + public static final field VIBRANT_PURPLE Ljava/lang/String; + public static final field VIOLET Ljava/lang/String; + public static final field VIOLET_BLUE Ljava/lang/String; + public static final field VIOLET_PINK Ljava/lang/String; + public static final field VIOLET_RED Ljava/lang/String; + public static final field VIRIDIAN Ljava/lang/String; + public static final field VIVID_BLUE Ljava/lang/String; + public static final field VIVID_GREEN Ljava/lang/String; + public static final field VIVID_PURPLE Ljava/lang/String; + public static final field VOMIT Ljava/lang/String; + public static final field VOMIT_GREEN Ljava/lang/String; + public static final field VOMIT_YELLOW Ljava/lang/String; + public static final field WARM_BLUE Ljava/lang/String; + public static final field WARM_BROWN Ljava/lang/String; + public static final field WARM_GREY Ljava/lang/String; + public static final field WARM_PINK Ljava/lang/String; + public static final field WARM_PURPLE Ljava/lang/String; + public static final field WASHED_OUT_GREEN Ljava/lang/String; + public static final field WATERMELON Ljava/lang/String; + public static final field WATER_BLUE Ljava/lang/String; + public static final field WEIRD_GREEN Ljava/lang/String; + public static final field WHEAT Ljava/lang/String; + public static final field WHITE Ljava/lang/String; + public static final field WINDOWS_BLUE Ljava/lang/String; + public static final field WINE Ljava/lang/String; + public static final field WINE_RED Ljava/lang/String; + public static final field WINTERGREEN Ljava/lang/String; + public static final field WISTERIA Ljava/lang/String; + public static final field YELLOW Ljava/lang/String; + public static final field YELLOWGREEN Ljava/lang/String; + public static final field YELLOWISH Ljava/lang/String; + public static final field YELLOWISH_BROWN Ljava/lang/String; + public static final field YELLOWISH_GREEN Ljava/lang/String; + public static final field YELLOWISH_ORANGE Ljava/lang/String; + public static final field YELLOWISH_TAN Ljava/lang/String; + public static final field YELLOWY_BROWN Ljava/lang/String; + public static final field YELLOWY_GREEN Ljava/lang/String; + public static final field YELLOW_BROWN Ljava/lang/String; + public static final field YELLOW_GREEN Ljava/lang/String; + public static final field YELLOW_OCHRE Ljava/lang/String; + public static final field YELLOW_ORANGE Ljava/lang/String; + public static final field YELLOW_TAN Ljava/lang/String; +} + diff --git a/plotly/plotlykt-core/build.gradle.kts b/plotly/plotlykt-core/build.gradle.kts new file mode 100644 index 00000000..fb953ab5 --- /dev/null +++ b/plotly/plotlykt-core/build.gradle.kts @@ -0,0 +1,37 @@ +plugins { + id("space.kscience.gradle.mpp") + `maven-publish` +} + +val dataforgeVersion: String by rootProject.extra +val plotlyVersion: String by rootProject.extra + + +kotlin{ + applyDefaultHierarchyTemplate() +} + +kscience { + fullStack(bundleName = "js/plotly-kt.js") + native() + wasm() + + dependencies { + api("space.kscience:dataforge-meta:$dataforgeVersion") + api(spclibs.kotlinx.html) +// api("org.jetbrains.kotlinx:kotlinx-html:0.11.0") + } + + jsMain{ + api(npm("plotly.js", plotlyVersion)) + } + + nativeMain { + implementation("com.squareup.okio:okio:3.3.0") + } +} + + +readme { + maturity = space.kscience.gradle.Maturity.DEVELOPMENT +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/Plot.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/Plot.kt new file mode 100644 index 00000000..54ec6343 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/Plot.kt @@ -0,0 +1,106 @@ +@file:OptIn(DFExperimental::class) + +package space.kscience.plotly + +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonArray +import kotlinx.serialization.json.buildJsonObject +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.meta.descriptors.Described +import space.kscience.dataforge.meta.descriptors.MetaDescriptor +import space.kscience.dataforge.meta.descriptors.node +import space.kscience.dataforge.misc.DFBuilder +import space.kscience.dataforge.misc.DFExperimental +import space.kscience.plotly.models.Layout +import space.kscience.plotly.models.Trace + +/** + * The main plot class. The changes to plot could be observed by attaching listener to root [meta] property. + */ +@DFBuilder +public class Plot( + override val meta: ObservableMutableMeta = ObservableMutableMeta(), +) : Configurable, MetaRepr, Described{ + + /** + * Ordered list ot traces in the plot + */ + public val data: List by meta.listOfScheme(Trace) + + /** + * Layout specification for th plot + */ + public val layout: Layout by meta.scheme(Layout) + + public fun addTrace(trace: Trace) { + meta.appendAndAttach("data", trace.meta) + } + + /** + * Append all traces from [traces] to the plot + */ + public fun traces(traces: Collection) { + traces.forEach { addTrace(it) } + } + + /** + * Append all [traces] + */ + public fun traces(vararg traces: Trace) { + traces.forEach { addTrace(it) } + } + + /** + * Remove a trace with a given [index] from the plot + */ + @UnstablePlotlyAPI + internal fun removeTrace(index: Int) { + meta.remove("data[$index]") + } + + override fun toMeta(): Meta = meta + + override val descriptor: MetaDescriptor get() = Companion.descriptor + + public companion object { + public val descriptor: MetaDescriptor = MetaDescriptor { + node(Plot::data.name, Trace) { + multiple = true + } + + node(Plot::layout.name, Layout) + } + } +} + +public fun Plot(meta: Meta): Plot = Plot(ObservableMutableMeta { update(meta) }) + +internal fun Plot.toJson(): JsonObject = buildJsonObject { + put("layout", layout.meta.toJson()) + put("data", buildJsonArray { + data.forEach { traceData -> + add(traceData.meta.toJson()) + } + }) +} + +/** + * Convert a plot to Json representation specified by Plotly `newPlot` command. + */ +public fun Plot.toJsonString(): String = toJson().toString() + +/** + * Configure the layout + */ +public inline fun Plot.layout(block: Layout.() -> Unit) { + layout.invoke(block) +} + +/** + * Add a generic trace + */ +public inline fun Plot.trace(block: Trace.() -> Unit): Trace { + val trace = Trace(block) + traces(trace) + return trace +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/Plotly.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/Plotly.kt new file mode 100644 index 00000000..9578edb0 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/Plotly.kt @@ -0,0 +1,66 @@ +package space.kscience.plotly + +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.buildJsonArray +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.Name +import kotlin.js.JsName + +/** + * A namespace for utility functions + */ +@JsName("PlotlyKt") +public object Plotly { + public const val VERSION: String = "2.24.1" + + public const val PLOTLY_CDN: String = "https://cdn.plot.ly/plotly-${VERSION}.min.js" + //"https://cdnjs.cloudflare.com/ajax/libs/plotly.js/${VERSION}/plotly.min.js" + + public val coordinateNames: List = listOf( + "x", "y", "z", "text", "hovertext", "close", "high", "low", "open", "locations", "lon", "lat", "ids" + ) + + public inline fun plot(block: Plot.() -> Unit): Plot = Plot().apply(block) +} + +/** + * Convert any type-safe configurator to json string + */ +public fun Scheme.toJsonString(): String = meta.toJson().toString() + +private fun List.toJson(): JsonArray = buildJsonArray { + forEach { add(it.meta.toJson()) } +} + +/** + * Convert list of type-safe configurators to json array string + */ +public fun List.toJsonString(): String = toJson().toString() + +@RequiresOptIn("Unstable API subjected to change in future releases", RequiresOptIn.Level.WARNING) +public annotation class UnstablePlotlyAPI + +@RequiresOptIn("This Plotly JS API is not fully supported. Use it at your own risk.", RequiresOptIn.Level.ERROR) +public annotation class UnsupportedPlotlyAPI + +public class PlotlyConfig : Scheme() { + public var editable: Boolean? by boolean() + public var showEditInChartStudio: Boolean? by boolean() + public var plotlyServerURL: String? by string() + public var responsive: Boolean? by boolean() + public var imageFormat: String? by string(Name.parse("toImageButtonOptions.format")) + + public fun withEditorButton() { + showEditInChartStudio = true + plotlyServerURL = "https://chart-studio.plotly.com" + } + + public fun saveAsSvg() { + imageFormat = "svg" + } + + override fun toString(): String = toJsonString() + + public companion object : SchemeSpec(::PlotlyConfig) +} + diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/PlotlyPage.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/PlotlyPage.kt new file mode 100644 index 00000000..d21ca62d --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/PlotlyPage.kt @@ -0,0 +1,65 @@ +package space.kscience.plotly + +import kotlinx.html.* +import kotlinx.html.stream.createHTML + +/** + * A custom HTML fragment including plotly container reference + */ +public class PlotlyFragment(public val render: FlowContent.(renderer: PlotlyRenderer) -> Unit) + +/** + * A complete page including headers and title + */ +public data class PlotlyPage( + val headers: Collection, + val fragment: PlotlyFragment, + val title: String = "Plotly.kt", + val renderer: PlotlyRenderer = StaticPlotlyRenderer +) { + public fun render(): String = createHTML().html { + head { + meta { + charset = "utf-8" + } + title(this@PlotlyPage.title) + headers.distinct().forEach { it.visit(consumer) } + } + body { + fragment.render(this, renderer) + } + } +} + +public fun Plotly.fragment(content: FlowContent.(renderer: PlotlyRenderer) -> Unit): PlotlyFragment = PlotlyFragment(content) + +/** + * Create a complete page including plots + */ +public fun Plotly.page( + vararg headers: PlotlyHtmlFragment = arrayOf(cdnPlotlyHeader), + title: String = "Plotly.kt", + renderer: PlotlyRenderer = StaticPlotlyRenderer, + content: FlowContent.(renderer: PlotlyRenderer) -> Unit +): PlotlyPage = PlotlyPage(headers.toList(), fragment(content), title, renderer) + +/** + * Convert an html plot fragment to page + */ +public fun PlotlyFragment.toPage( + vararg headers: PlotlyHtmlFragment = arrayOf(cdnPlotlyHeader), + title: String = "Plotly.kt", + renderer: PlotlyRenderer = StaticPlotlyRenderer +): PlotlyPage = PlotlyPage(headers.toList(), this, title, renderer) + +/** + * Convert a plot to the sigle-plot page + */ +public fun Plot.toPage( + vararg headers: PlotlyHtmlFragment = arrayOf(cdnPlotlyHeader), + config: PlotlyConfig = PlotlyConfig.empty(), + title: String = "Plotly.kt", + renderer: PlotlyRenderer = StaticPlotlyRenderer +): PlotlyPage = PlotlyFragment { + plot(this@toPage, config = config, renderer = renderer) +}.toPage(*headers, title = title) \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/PlotlyRenderer.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/PlotlyRenderer.kt new file mode 100644 index 00000000..1dc43ecb --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/PlotlyRenderer.kt @@ -0,0 +1,54 @@ +package space.kscience.plotly + +import kotlinx.html.* + +public interface PlotlyRenderer { + public fun FlowContent.renderPlot( + plot: Plot, + plotId: String = plot.toString(), + config: PlotlyConfig = PlotlyConfig() + ): Plot +} + +public object StaticPlotlyRenderer : PlotlyRenderer { + override fun FlowContent.renderPlot(plot: Plot, plotId: String, config: PlotlyConfig): Plot { + div { + id = plotId + script { + val tracesString = plot.data.toJsonString() + val layoutString = plot.layout.toJsonString() + unsafe { + //language=JavaScript + +""" + Plotly.react( + '$plotId', + $tracesString, + $layoutString, + $config + ); + """.trimIndent() + } + } + } + return plot + } +} + +public fun FlowContent.plot( + plot: Plot, + plotId: String = plot.toString(), + config: PlotlyConfig = PlotlyConfig(), + renderer: PlotlyRenderer = StaticPlotlyRenderer +): Plot = with(renderer) { + renderPlot(plot, plotId, config) +} + +public fun FlowContent.plot( + plotId: String? = null, + config: PlotlyConfig = PlotlyConfig(), + renderer: PlotlyRenderer = StaticPlotlyRenderer, + builder: Plot.() -> Unit +): Plot { + val plot = Plot().apply(builder) + return plot(plot, plotId ?: plot.toString(), config, renderer) +} diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/dfExt.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/dfExt.kt new file mode 100644 index 00000000..fffde72e --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/dfExt.kt @@ -0,0 +1,203 @@ +package space.kscience.plotly + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.misc.DFExperimental +import space.kscience.dataforge.names.* +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty +import kotlin.time.Duration +import kotlin.time.DurationUnit +import kotlin.time.toDuration + +//extensions for DataForge + + +/** + * List of values delegate + */ +internal fun Scheme.listOfValues( + key: Name? = null, +): ReadWriteProperty> = object : ReadWriteProperty> { + override fun getValue(thisRef: Any?, property: KProperty<*>): List { + val name = key ?: property.name.asName() + return meta[name]?.value?.list ?: emptyList() + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: List) { + val name = key ?: property.name.asName() + meta[name] = value.asValue() + } +} + +/** + * A safe [Double] range + */ +internal fun Scheme.doubleInRange( + range: ClosedFloatingPointRange, + defaultValue: Double = Double.NaN, + key: Name? = null, +): ReadWriteProperty = object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Double { + val name = key ?: property.name.asName() + return meta[name].double ?: defaultValue + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) { + val name = key ?: property.name.asName() + if (value in range) { + meta[name] = value + } else { + error("$value not in range $range") + } + } +} + +/** + * A safe [Double] ray + */ +internal fun Scheme.doubleGreaterThan( + minValue: Double, + key: Name? = null, +): ReadWriteProperty = object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Double { + val name = key ?: property.name.asName() + return meta[name].double ?: Double.NaN + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) { + val name = key ?: property.name.asName() + if (value >= minValue) { + meta[name] = value + } else { + error("$value less than $minValue") + } + } +} + + +/** + * A safe [Int] ray + */ +internal fun Scheme.intGreaterThan( + minValue: Int, + key: Name? = null, +): ReadWriteProperty = object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Int { + val name = key ?: property.name.asName() + return meta[name].int ?: minValue + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { + val name = key ?: property.name.asName() + if (value >= minValue) { + meta[name] = value + } else { + error("$value less than $minValue") + } + } +} + +/** + * A safe [Int] range + */ +internal fun Scheme.intInRange( + range: ClosedRange, + key: Name? = null, +): ReadWriteProperty = object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Int { + val name = key ?: property.name.asName() + return meta[name].int ?: 0 + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { + val name = key ?: property.name.asName() + if (value in range) { + meta[name] = value + } else { + error("$value not in range $range") + } + } +} + +/** + * A safe [Number] ray + */ +public fun Scheme.numberGreaterThan( + minValue: Number, + default: Number = minValue, + key: Name? = null, +): ReadWriteProperty = object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Number { + val name = key ?: property.name.asName() + return meta[name].number ?: default + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Number) { + val name = key ?: property.name.asName() + if (value.toDouble() >= minValue.toDouble()) { + meta[name] = value + } else { + error("$value less than $minValue") + } + } +} + +/** + * A safe [Number] range + */ +public fun Scheme.numberInRange( + range: ClosedRange, + key: Name? = null, +): ReadWriteProperty = object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Number { + val name = key ?: property.name.asName() + return meta[name].int ?: 0 + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Number) { + val name = key ?: property.name.asName() + if (value.toDouble() in range) { + meta[name] = value + } else { + error("$value not in range $range") + } + } +} + +internal fun Scheme.duration( + default: Duration? = null, + key: Name? = null, +): ReadWriteProperty = object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Duration? { + val name = key ?: property.name.asName() + val value = meta[name]?.value + val units = meta[name + "unit"]?.enum() ?: DurationUnit.MILLISECONDS + return value?.long?.toDuration(units) ?: default + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Duration?) { + val name = key ?: property.name.asName() + if (value == null) { + meta.remove(name) + } else { + meta.value = value.toDouble(DurationUnit.MILLISECONDS).asValue() + meta[name + "unit"] = DurationUnit.MILLISECONDS.name + } + } +} + +/** + * Append the observable note to same-name-siblings and observe its changes. + */ +@OptIn(DFExperimental::class) +internal fun ObservableMutableMeta.appendAndAttach(key: String, meta: ObservableMutableMeta) { + val name = Name.parse(key) + require(!name.isEmpty()) { "Name could not be empty for append operation" } + val newIndex = name.lastOrNull()!!.index + if (newIndex != null) { + attach(name, meta) + } else { + val index = (getIndexed(name).keys.mapNotNull { it?.toIntOrNull() }.maxOrNull() ?: -1) + 1 + attach(name.withIndex(index.toString()), meta) + } +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/events/PlotlyEvent.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/events/PlotlyEvent.kt new file mode 100644 index 00000000..89d29be1 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/events/PlotlyEvent.kt @@ -0,0 +1,28 @@ +package space.kscience.plotly.events + +import kotlinx.serialization.json.JsonElement +import space.kscience.dataforge.meta.Value + +public enum class PlotlyEventListenerType(public val eventType: String){ + CLICK("plotly_click"), + HOVER("plotly_hover"), + UNHOVER("plotly_unhover"), + SELECTING("plotly_selecting"), + SELECTED("plotly_selected") +} + +public data class PlotlyEventPoint( + public val curveNumber: Int, + public val data: JsonElement, + public val pointNumber: Int? = null, + public val x: Value? = null, + public val y: Value? = null, +// +// public var data: Trace by scheme(Trace) +// public var fullData: Trace by scheme(Trace) +) + + +public data class PlotlyEvent(public val points: List) + + diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/html.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/html.kt new file mode 100644 index 00000000..82b9cbd9 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/html.kt @@ -0,0 +1,64 @@ +package space.kscience.plotly + +import kotlinx.html.* +import kotlinx.html.stream.createHTML + + +public class PlotlyHtmlFragment(public val visit: TagConsumer<*>.() -> Unit) { + override fun toString(): String { + return createHTML().also(visit).finalize() + } +} + +public operator fun PlotlyHtmlFragment.plus(other: PlotlyHtmlFragment): PlotlyHtmlFragment = PlotlyHtmlFragment { + this@plus.run { visit() } + other.run { visit() } +} + +public val cdnPlotlyHeader: PlotlyHtmlFragment = PlotlyHtmlFragment { + script { + type = "text/javascript" + src = Plotly.PLOTLY_CDN + } +} + +/** + * Create a html (including headers) string from plot + */ +public fun Plot.toHTML( + vararg headers: PlotlyHtmlFragment = arrayOf(cdnPlotlyHeader), + config: PlotlyConfig = PlotlyConfig(), +): String = createHTML().html { + head { + meta { + charset = "utf-8" + } + title(layout.title ?: "Plotly.kt") + headers.forEach { + it.visit(consumer) + } + } + body { + StaticPlotlyRenderer.run { + renderPlot(this@toHTML, this@toHTML.toString(), config) + } + } +} + +public val mathJaxHeader: PlotlyHtmlFragment = PlotlyHtmlFragment { + script { + type = "text/x-mathjax-config" + unsafe { + +""" + MathJax.Hub.Config({ + tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]} + }); + """ + } + } + script { + type = "text/javascript" + async = true + src = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_SVG" + } +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Axis.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Axis.kt new file mode 100644 index 00000000..6ec6ff9c --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Axis.kt @@ -0,0 +1,299 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.listOfValues +import space.kscience.plotly.numberGreaterThan +import space.kscience.plotly.numberInRange +import kotlin.js.JsName + + +public enum class AxisType { + @JsName("default") + `-`, + linear, + log, + date, + category, + multicategory; +} + +public enum class TickMode { + array, + auto, + linear +} + +public enum class Ticks { + @Suppress("EnumEntryName", "DANGEROUS_CHARACTERS") + @JsName("empty") + `""`, + inside, + outside +} + +public enum class AxisSide { + top, bottom, left, right +} + +/** + * Axis scheme + */ +public class Axis : Scheme() { + /** + * Sets the title of this axis. + */ + public var title: String? + get() = meta["title.text"].string ?: meta["title"].string + set(value) { + meta["title"] = value?.asValue() + } + + /** + * Enumerated, one of ( "-" | "linear" | "log" | "date" | "category" | "multicategory" ) . + * Sets the axis type. By default, plotly attempts to determine + * the axis type by looking into the data of the traces + * that referenced the axis in question. + * Default: "-" + */ + public var type: AxisType by enum(AxisType.`-`) + + /** + * A single toggle to hide the axis while preserving interaction + * like dragging. Default is true when a cheater plot + * is present on the axis, otherwise false + */ + public var visible: Boolean? by boolean() + + /** + * Sets the tick length (in px). + * Default: 5. + */ + public var ticklen: Number by numberGreaterThan(0) + + /** + * Sets the tick width (in px). + * Default: 1. + */ + public var tickwidth: Number by numberGreaterThan(0) + + /** + * Sets the tick color. + * Default: #444. + */ + public val tickcolor: Color by color() + + /** + * Sets the angle of the tick labels with respect to the horizontal. + * For example, a `tickangle` of -90 draws the tick labels vertically. + */ + public var tickangle: Number by numberInRange(-360.0..360.0) + + /** + * Sets the tick font. + */ + public var tickfont: Font by scheme(Font) + + /** + * Determines whether ticks are drawn or not. If "", this axis' ticks are not drawn. + * If "outside" ("inside"), this axis' are drawn outside (inside) the axis lines. + */ + public var ticks: Ticks by enum(Ticks.inside) + + /** + * Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings + * available to "log" and "date" axes. If the axis `type` is "log", then ticks are set every 10^(n"dtick) + * where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. + * To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... + * set dtick to log_10(5), or 0.69897000433. "log" has several special values; "L", where `f` + * is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, + * `dtick` = "L0.5" will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, + * use "D1" (all digits) or "D2" (only 2 and 5). `tick0` is ignored for "D1" and "D2". If the axis `type` is "date", + * then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, + * set `dtick` to 86400000.0. "date" also has special values "M" gives ticks spaced by a number of months. + * `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to "2000-01-15" + * and `dtick` to "M3". To set ticks every 4 years, set `dtick` to "M48" + */ + public var dtick: Value? by value() + + /** + * Determines whether or not the range of this axis is computed + * in relation to the input data. See `rangemode` for more info. + * If `range` is provided, then `autorange` is set to "false". + * Default: true. + */ + public var autorange: Boolean by boolean(true) + + /** + * Sets the range of this axis. If the axis `type` is "log", + * then you must take the log of your desired range + * (e.g. to set the range from 1 to 100, set the range from 0 to 2). + * If the axis `type` is "date", it should be date strings, like date data, + * though Date objects and unix milliseconds will be accepted and + * converted to strings. If the axis `type` is "category", it should be + * numbers, using the scale where each category is assigned + * a serial number from zero in the order it appears. + */ + @Deprecated("Use range() instead") + public var range: ClosedFloatingPointRange? + get() = meta["range"]?.value?.doubleArray?.let { it[0]..it[1] } + set(value) { + meta["range"] = value?.let { ListValue(listOf(value.start.asValue(), value.endInclusive.asValue())) } + } + + /** + * Set the range using arbitrary values + */ + public fun range(from: Value, to: Value) { + meta["range"] = ListValue(listOf(from, to)) + } + + /** + * Set range using double kotlin range + */ + public fun range(value: ClosedFloatingPointRange) { + range(value.start.asValue(), value.endInclusive.asValue()) + } + + /** + * Set range using kotlin string range + */ + public fun range(value: ClosedRange) { + range(value.start.asValue(), value.endInclusive.asValue()) + } + + + /** + * Sets default for all colors associated with this axis all at once: + * line, font, tick, and grid colors. Grid color is lightened + * by blending this with the plot background Individual pieces can override this. + * Default: #444. + */ + public val color: Color by color() + + /** + * Determines whether or not a line bounding this axis is drawn. + */ + public var showline: Boolean? by boolean() + + /** + * Sets the axis line color. Default: #444. + */ + public val linecolor: Color by color() + + /** + * Sets the width (in px) of the axis line. Default: 1. + */ + public var linewidth: Number by numberGreaterThan(0) + + /** + * Determines whether or not grid lines are drawn. If "true", + * the grid lines are drawn at every tick mark. + */ + public var showgrid: Boolean? by boolean() + + /** + * Sets the color of the grid lines. Default: #eee + */ + public val gridcolor: Color by color() + + /** + * Sets the width (in px) of the grid lines. Default: 1. + */ + public var gridwidth: Number by numberGreaterThan(0) + + /** + * Determines whether or not a line is drawn at along the 0 value of this axis. + * If "true", the zero line is drawn on top of the grid lines. + */ + public var zeroline: Boolean? by boolean() + + /** + * Sets the line color of the zero line. Default: #444 + */ + public val zerolinecolor: Color by color() + + /** + * Sets the width (in px) of the zero line. Default: 1. + */ + public var zerolinewidth: Number by numberGreaterThan(0) + + /** + * Sets the tick mode for this axis. If "auto", the number of ticks is set via `nticks`. + * If "linear", the placement of the ticks is determined by a starting position `tick0` + * and a tick step `dtick` ("linear" is the default value if `tick0` and `dtick` are provided). + * If "array", the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. + * ("array" is the default value if `tickvals` is provided). + */ + public var tickmode: TickMode by enum(TickMode.auto) + + /** + * Sets the values at which ticks on this axis appear. + * Only has an effect if `tickmode` is set to "array". Used with `ticktext`. + */ + public var tickvals: List by listOfValues() + + /** + *Sets the text displayed at the ticks position via `tickvals`. + * Only has an effect if `tickmode` is set to "array". Used with `tickvals`. + */ + public var ticktext: List by listOfValues() + + /** + * Determines whether or not the tick labels are drawn. + */ + public var showticklabels: Boolean? by boolean() + + public var autotick: Boolean? by boolean() + + /** + * Determines whether long tick labels automatically grow the figure margins. + */ + public var automargin: Boolean? by boolean() + + /** + * Enumerated, one of ( "free" | "/^x([2-9]|[1-9][0-9]+)?$/" | "/^y([2-9]|[1-9][0-9]+)?$/" ) + * If set to an opposite-letter axis id (e.g. `x2`, `y`), this axis is bound to the corresponding + * opposite-letter axis. If set to "free", this axis' position is determined by `position`. + */ + public var anchor: String? by string() + + /** + * Sets the position of this axis in the plotting space (in normalized coordinates). + * Only has an effect if `anchor` is set to "free". Default: 0. + */ + public var position: Number by numberInRange(0.0..1.0) + + /** + * Determines whether a x (y) axis is positioned at the "bottom" ("left") or "top" ("right") of the plotting area. + */ + public var side: AxisSide? by value( + writer = { it?.name?.asValue() }, + reader = { value -> value?.string?.let { enumValueOf(it) } } + ) + + /** + * If set a same-letter axis id, this axis is overlaid on top of the corresponding same-letter axis, + * with traces and axes visible for both axes. If "false", this axis does not overlay any same-letter axes. + * In this case, for axes with overlapping domains only the highest-numbered axis will be visible. + */ + public var overlaying: String? by string() + + public fun title(block: Title.() -> Unit) { + val spec = Title.write(meta.getOrCreate("title")) + spec.apply(block) + } + + public fun tickfont(block: Font.() -> Unit) { + tickfont = Font(block) + } + + public fun tickvals(array: Iterable) { + tickvals = array.map { Value.of(it) } + } + + public fun ticktext(array: Iterable) { + ticktext = array.map { Value.of(it) } + } + + public companion object : SchemeSpec(::Axis) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Bar.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Bar.kt new file mode 100644 index 00000000..9abf2779 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Bar.kt @@ -0,0 +1,66 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.asName +import space.kscience.plotly.numberGreaterThan + +public class Bar : Trace(), SelectedPoints { + init { + type = TraceType.bar + } + + /** + * Array containing integer indices of selected points. Has an effect only for traces that support selections. + * Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, + * any other non-array values means no selection all where the `selected` and `unselected` styles have no effect. + */ + override var selectedpoints: List by numberList() + + override var selected: SelectPoints by scheme(SelectPoints) + + override var unselected: SelectPoints by scheme(SelectPoints) + + /** + * Sets where the bar base is drawn (in position axis units). In "stack" or "relative" barmode, + * traces that set "base" will be excluded and drawn in "overlay" mode instead. + */ + public var base: List by numberList() + + /** + * Sets the bar width (in position axis units). + */ + public var width: Number by numberGreaterThan(0) + + /** + * Array of numbers greater than or equal to 0. Sets the bar width (in position axis units). + */ + public var widthList: List by numberList(key = "width".asName()) + + /** + * Shifts the position where the bar is drawn (in position axis units). In "group" barmode, + * traces that set "offset" will be excluded and drawn in "overlay" mode instead. + */ + public var offset: Number? by number() + + /** + * Shifts the position where the bar is drawn (in position axis units). In "group" barmode, + * traces that set "offset" will be excluded and drawn in "overlay" mode instead. + */ + public var offsetsList: List by numberList(key = "offset".asName()) + + + /** + * Constrain the size of text inside or outside a bar to be no larger than the bar itself. + */ + public var constraintext: ConstrainText by enum(ConstrainText.both) + + public fun selected(block: SelectPoints.() -> Unit) { + selected = SelectPoints(block) + } + + public fun unselected(block: SelectPoints.() -> Unit) { + unselected = SelectPoints(block) + } + + public companion object : SchemeSpec(::Bar) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Box.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Box.kt new file mode 100644 index 00000000..46eec003 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Box.kt @@ -0,0 +1,224 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.doubleInRange +import space.kscience.plotly.listOfValues +import space.kscience.plotly.numberGreaterThan +import kotlin.js.JsName + +public enum class BoxMean { + `true`, + sd, + `false` +} + +public enum class BoxPoints { + all, + outliers, + suspectedoutliers, + `false` +} + +public enum class QuartileMethod { + linear, + exclusive, + inclusive +} + +public enum class BoxHoveron { + boxes, + points, + + @JsName("boxesAndPoints") + `boxes+points` +} + +public class Box : Trace(), SelectedPoints { + init { + type = TraceType.box + } + + /** + * Sets the width of the box in data coordinate If "0" (default value) the width is + * automatically selected based on the positions of other box traces in the same subplot. + */ + public var width: Number by numberGreaterThan(0) + + /** + * If "true", the mean of the box(es)' underlying distribution is drawn as a dashed line + * inside the box(es). If "sd" the standard deviation is also drawn. Defaults to "true" + * when `mean` is set. Defaults to "sd" when `sd` is set Otherwise defaults to "false". + */ + public var boxmean: BoxMean by enum(BoxMean.`false`) + + /** + * If "outliers", only the sample points lying outside the whiskers are shown + * If "suspectedoutliers", the outlier points are shown and points either less + * than 4"Q1-3"Q3 or greater than 4"Q3-3"Q1 are highlighted (see `outliercolor`) + * If "all", all sample points are shown If "false", only the box(es) are shown + * with no sample points Defaults to "suspectedoutliers" when `marker.outliercolor` + * or `marker.line.outliercolor` is set. Defaults to "all" under the q1/median/q3 signature. + * Otherwise defaults to "outliers". + */ + public var boxpoints: BoxPoints by enum(BoxPoints.all) + + /** + * Determines whether or not notches are drawn. Notches displays a confidence interval + * around the median. We compute the confidence interval as median +/- 1.57 " IQR / sqrt(N), + * where IQR is the interquartile range and N is the sample size. If two boxes' notches + * do not overlap there is 95% confidence their medians differ. + * See https://sites.google.com/site/davidsstatistics/home/notched-box-plots for more info. + * Defaults to "false" unless `notchwidth` or `notchspan` is set. + */ + public var notched: Boolean? by boolean() + + /** + * Sets the width of the notches relative to the box' width. + * For example, with 0, the notches are as wide as the box(es). + * Default: 0.25. + */ + public var notchwidth: Double by doubleInRange(0.0..0.5) + + /** + * Sets the notch span from the boxes' `median` values. There should be as many items + * as the number of boxes desired. This attribute has effect only under the q1/median/q3 signature. + * If `notchspan` is not provided but a sample (in `y` or `x`) is set, we compute it + * as 1.57 " IQR / sqrt(N), where N is the sample size. + */ + public var notchspan: List by listOfValues() + + /** + * Sets the width of the whiskers relative to the box' width. For example, with 1, + * the whiskers are as wide as the box(es). Default: 0.5. + */ + public var whiskerwidth: Double by doubleInRange(0.0..1.0) + + /** + * Sets the Quartile 1 values. There should be as many items as the number of boxes desired. + */ + public var q1: List by listOfValues() + + /** + * Sets the Quartile 3 values. There should be as many items as the number of boxes desired. + */ + public var q3: List by listOfValues() + + /** + * Sets the median values. There should be as many items as the number of boxes desired. + */ + public var median: List by listOfValues() + + /** + * Sets the mean values. There should be as many items as the number of boxes desired. + * This attribute has effect only under the q1/median/q3 signature. If `mean` is not provided + * but a sample (in `y` or `x`) is set, we compute the mean for each box using the sample values. + */ + public var mean: List by listOfValues() + + /** + * Sets the standard deviation values. There should be as many items as the number of boxes desired. + * This attribute has effect only under the q1/median/q3 signature. If `sd` is not provided + * but a sample (in `y` or `x`) is set, we compute the standard deviation for each box using the sample values. + */ + public var sd: List by listOfValues() + + /** + * Sets the lower fence values. There should be as many items as the number of boxes desired. + * This attribute has effect only under the q1/median/q3 signature. If `lowerfence` is not provided + * but a sample (in `y` or `x`) is set, we compute the lower as the last sample point below 1.5 times the IQR. + */ + public var lowerfence: List by listOfValues() + + /** + * Sets the upper fence values. There should be as many items as the number of boxes desired. + * This attribute has effect only under the q1/median/q3 signature. If `upperfence` is not provided + * but a sample (in `y` or `x`) is set, we compute the lower as the last sample point above 1.5 times the IQR. + */ + public var upperfence: List by listOfValues() + + /** + * Sets the method used to compute the sample's Q1 and Q3 quartiles. The "linear" method uses + * the 25th percentile for Q1 and 75th percentile for Q3 as computed using method #10 + * (listed on http://www.amstat.org/publications/jse/v14n3/langford.html). The "exclusive" method + * uses the median to divide the ordered dataset into two halves if the sample is odd, + * it does not include the median in either half - Q1 is then the median of the lower half and Q3 + * the median of the upper half. The "inclusive" method also uses the median to divide the ordered dataset + * into two halves but if the sample is odd, it includes the median in both halves - Q1 is then the median + * of the lower half and Q3 the median of the upper half. + */ + public var quartilemethod: QuartileMethod by enum(QuartileMethod.linear) + + /** + * Array containing integer indices of selected points. Has an effect only for traces that support selections. + * Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, + * any other non-array values means no selection all where the `selected` and `unselected` styles have no effect. + */ + override var selectedpoints: List by numberList() + + override var selected: SelectPoints by scheme(SelectPoints) + + override var unselected: SelectPoints by scheme(SelectPoints) + + /** + * Sets the amount of jitter in the sample points drawn. + * If "0", the sample points align along the distribution axis. + * If "1", the sample points are drawn in a random jitter + * of width equal to the width of the violins. + */ + public var jitter: Double by doubleInRange(0.0..1.0) + + /** + * Sets the position of the sample points in relation to the violins. + * If "0", the sample points are places over the center of the violins. + * Positive (negative) values correspond to positions to the right (left) + * for vertical violins and above (below) for horizontal violins. + */ + public var pointpos: Double by doubleInRange(-2.0..2.0) + + /** + * Do the hover effects highlight individual boxes or sample points or both? + */ + public var hoveron: BoxHoveron by enum(BoxHoveron.`boxes+points`) + + public fun q1(array: Iterable) { + q1 = array.map { Value.of(it) } + } + + public fun q3(array: Iterable) { + q3 = array.map { Value.of(it) } + } + + public fun median(array: Iterable) { + median = array.map { Value.of(it) } + } + + public fun lowerfence(array: Iterable) { + lowerfence = array.map { Value.of(it) } + } + + public fun upperfence(array: Iterable) { + upperfence = array.map { Value.of(it) } + } + + public fun notchspan(array: Iterable) { + notchspan = array.map { Value.of(it) } + } + + public fun mean(array: Iterable) { + mean = array.map { Value.of(it) } + } + + public fun sd(array: Iterable) { + sd = array.map { Value.of(it) } + } + + public fun selected(block: SelectPoints.() -> Unit) { + selected = SelectPoints(block) + } + + public fun unselected(block: SelectPoints.() -> Unit) { + unselected = SelectPoints(block) + } + + public companion object : SchemeSpec(::Box) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/CandleStick.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/CandleStick.kt new file mode 100644 index 00000000..98f811e9 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/CandleStick.kt @@ -0,0 +1,84 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.asName +import space.kscience.plotly.doubleInRange + + +public enum class XPeriodAlignment{ + start, + middle, + end +} + +public class CandleStickLine: Scheme(){ + public val fillcolor: Color by color() + public val lineColor: Color by color(Name.parse("line.color")) + public var lineWidth: Double by double(2.0, key = Name.parse("line.width")) + public companion object: SchemeSpec(::CandleStickLine) +} + +public class CandleStick : Trace() { + init { + type = TraceType.candlestick + } + + /** + * Assigns id labels to each datum. These ids for object constancy of data points during animation. + * Should be an array of strings, not numbers or any other type. + */ + public var ids: List? by stringList() + + /** + * Only relevant when the axis `type` is "date". Sets the period positioning in milliseconds or "M" on the x axis. + * Special values in the form of "M" could be used to declare the number of months. In this case `n` must be a positive integer. + * Default 0 + */ + public var xperiod: Value by value { 0.asValue() } + + public var xperiod0: Value? by value() + + /** + * Only relevant when the axis `type` is "date". Sets the alignment of data points on the x axis. + */ + public var xperiodalignment: XPeriodAlignment by enum(XPeriodAlignment.middle) + + public val open: TraceValues by axis + public val high: TraceValues by axis + public val close: TraceValues by axis + public val low: TraceValues by axis + + + public var candleStickMeta: Value? by value("meta".asName()) + + /** + * Sets a reference between this trace's x coordinates and a 2D cartesian x axis. If "x" (the default value), + * the x coordinates refer to `layout.xaxis`. If "x2", the x coordinates refer to `layout.xaxis2`, and so on. + * Default "x" + */ + public var xaxis: String by string("x") + + /** + * Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If "y" (the default value), + * the y coordinates refer to `layout.yaxis`. If "y2", the y coordinates refer to `layout.yaxis2`, and so on. + */ + public var yaxis: String by string("y") + + + public var lineWidth: Double by double(2.0, Name.parse("line.width")) + + public var increasing: CandleStickLine by scheme(CandleStickLine) + public var decreasing: CandleStickLine by scheme(CandleStickLine) + + /** + * Number between 0 and 1. + * + * Selects the width of the whiskers relative to the box´s width. + * For example, with 1, the whiskers are as wide as the box(es). + * Default 0 + */ + public var whiskerwidth: Double by doubleInRange(0.0..1.0) + + public companion object: SchemeSpec(::CandleStick) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Color.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Color.kt new file mode 100644 index 00000000..7b242940 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Color.kt @@ -0,0 +1,40 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.asName +import kotlin.properties.ReadOnlyProperty + +/** + * A color value customizer + * TODO add a hook for descriptor generation + */ +public class Color internal constructor(parent: Scheme, key: Name) { + public var value: Value? by parent.value(key = key) + + public var string: String? + get() = value?.string + set(value) { + this.value = value?.asValue() + } + + public operator fun invoke(value: String): Unit { + this.value = value.asValue() + } + + public operator fun invoke(value: Number): Unit { + this.value = value.asValue() + } + + public operator fun invoke(red: Number, green: Number, blue: Number) { + invoke("rgb(${red.toFloat()},${green.toFloat()},${blue.toFloat()})") + } + + public operator fun invoke(red: Number, green: Number, blue: Number, alpha: Number) { + invoke("rgba(${red.toFloat()},${green.toFloat()},${blue.toFloat()},${alpha.toFloat()})") + } +} + +public fun Scheme.color(key: Name? = null): ReadOnlyProperty = ReadOnlyProperty { _, property -> + Color(this, key ?: property.name.asName()) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Contour.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Contour.kt new file mode 100644 index 00000000..e46f9cfb --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Contour.kt @@ -0,0 +1,48 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.dataforge.meta.boolean +import space.kscience.dataforge.meta.enum +import space.kscience.dataforge.meta.scheme +import space.kscience.plotly.intGreaterThan + +public class Contour : Trace(), HeatmapContour, ContourSpec { + init { + type = TraceType.contour + } + + /** + * If "array", the heatmap's x coordinates are given by "x" (the default behavior when `x` is provided). + * If "scaled", the heatmap's x coordinates are given by "x0" and "dx" (the default behavior when `x` is not provided). + */ + override var xtype: DataType by enum(DataType.array) + + /** + * If "array", the heatmap's y coordinates are given by "y" (the default behavior when `y` is provided) + * If "scaled", the heatmap's y coordinates are given by "y0" and "dy" (the default behavior when `y` is not provided) + */ + override var ytype: DataType by enum(DataType.array) + + /** + * Sets the maximum number of contour levels. The actual number of contours + * will be chosen automatically to be less than or equal to the value of `ncontours`. + * Has an effect only if `autocontour` is "true" or if `contours.size` is missing. + * Default: 15. + */ + override var ncontours: Int by intGreaterThan(1) + + override var contours: Contours by scheme(Contours) + + /** + * Determines whether or not the contour level attributes are picked by an algorithm. + * If "true" (default), the number of contour levels can be set in `ncontours`. + * If "false", set the contour level attributes in `contours`. + */ + override var autocontour: Boolean? by boolean() + + public fun contours(block: Contours.() -> Unit) { + contours = Contours(block) + } + + public companion object : SchemeSpec(::Contour) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/ContourSpec.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/ContourSpec.kt new file mode 100644 index 00000000..adf7214b --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/ContourSpec.kt @@ -0,0 +1,68 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.numberGreaterThan + +public class Contours : Scheme() { + /** + * If `levels`, the data is represented as a contour plot with multiple + * levels displayed. If `constraint`, the data is represented as constraints + * with the invalid region shaded as specified by the `operation` and `value` parameters. + */ + public var type: ContoursType by enum(ContoursType.levels) + + /** + * Sets the starting contour level value. Must be less than `contours.end` + */ + public var start: Number? by number() + + /** + * Sets the end contour level value. Must be more than `contours.start` + */ + public var end: Number? by number() + + /** + * Sets the step between each contour level. Must be positive. + */ + public var size: Number by numberGreaterThan(0) + + /** + * Determines the coloring method showing the contour values. + * If "fill" (default), coloring is done evenly between each contour level + * If "heatmap", a heatmap gradient coloring is applied between each contour level. + * If "lines", coloring is done on the contour lines. If "none", + * no coloring is applied on this trace. + */ + public var coloring: ContoursColoring by enum(ContoursColoring.fill) + + /** + * Determines whether or not the contour lines are drawn. + * Has an effect only if `contours.coloring` is set to "fill". + */ + public var showlines: Boolean? by boolean() + + /** + * Determines whether to label the contour lines with their values. + */ + public var showlabels: Boolean? by boolean() + + /** + * Sets the font used for labeling the contour levels. The default color + * comes from the lines, if shown. The default family and size come from `layout.font`. + */ + public var labelfont: Font by scheme(Font) + + public fun labelfont(block: Font.() -> Unit) { + labelfont = Font(block) + } + + public companion object : SchemeSpec(::Contours) +} + +public interface ContourSpec { + public var ncontours: Int + + public var contours: Contours + + public var autocontour: Boolean? +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Heatmap.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Heatmap.kt new file mode 100644 index 00000000..e3c7e378 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Heatmap.kt @@ -0,0 +1,48 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.dataforge.meta.enum +import space.kscience.plotly.numberGreaterThan + +public open class Heatmap : Trace(), Table2D, HeatmapContour { + init { + type = TraceType.heatmap + } + + /** + * Sets the horizontal gap (in pixels) between bricks. + */ + override var xgap: Number by numberGreaterThan(0) + + /** + * Sets the vertical gap (in pixels) between bricks. + */ + override var ygap: Number by numberGreaterThan(0) + + /** + * Picks a smoothing algorithm use to smooth `z` data. + */ + override var zsmooth: ZsmoothType by enum(ZsmoothType.best) + + /** + * If "array", the heatmap's x coordinates are given by "x" (the default behavior when `x` is provided). + * If "scaled", the heatmap's x coordinates are given by "x0" and "dx" (the default behavior when `x` is not provided). + */ + override var xtype: DataType by enum(DataType.array) + + /** + * If "array", the heatmap's y coordinates are given by "y" (the default behavior when `y` is provided) + * If "scaled", the heatmap's y coordinates are given by "y0" and "dy" (the default behavior when `y` is not provided) + */ + override var ytype: DataType by enum(DataType.array) + + public companion object : SchemeSpec(::Heatmap) +} + +public class HeatmapGL : Heatmap() { + init { + type = TraceType.heatmapgl + } + + public companion object : SchemeSpec(::HeatmapGL) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/HeatmapContour.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/HeatmapContour.kt new file mode 100644 index 00000000..41d468c6 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/HeatmapContour.kt @@ -0,0 +1,12 @@ +package space.kscience.plotly.models + +public enum class DataType { + array, + scaled +} + +public interface HeatmapContour { + public var xtype: DataType + + public var ytype: DataType +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Histogram.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Histogram.kt new file mode 100644 index 00000000..75163070 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Histogram.kt @@ -0,0 +1,265 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.intGreaterThan +import space.kscience.plotly.numberGreaterThan +import kotlin.js.JsName + + +public enum class HistFunc { + count, + sum, + + @JsName("avg") + average, + min, + max +} + +public enum class HistNorm { + empty, + percent, + probability, + density, + + @JsName("probabilityDensity") + `probability density` +} + +public class Bins : Scheme() { + //FIXME("add categorical coordinate string") + + /** + * Sets the starting value for the x axis bins. + * Defaults to the minimum data value, shifted down + * if necessary to make nice round values and to remove + * ambiguous bin edges. For example, if most of the data + * is integers we shift the bin edges 0.5 down, so a `size` + * of 5 would have a default `start` of -0.5, so it is clear + * that 0-4 are in the first bin, 5-9 in the second, but + * continuous data gets a start of 0 and bins [0,5), [5,10) etc. + * Dates behave similarly, and `start` should be a date string. + * For category data, `start` is based on the category + * serial numbers, and defaults to -0.5. + */ + public var start: Number? by number() + + /** + * Sets the end value for the x axis bins. The last bin may + * not end exactly at this value, we increment the bin edge + * by `size` from `start` until we reach or exceed `end`. + * Defaults to the maximum data value. Like `start`, for + * dates use a date string, and for category data `end` + * is based on the category serial numbers. + */ + public var end: Number? by number() + + /** + * Sets the size of each x axis bin. Default behavior: + * If `nbinsx` is 0 or omitted, we choose a nice round + * bin size such that the number of bins is about + * the same as the typical number of samples in each bin. + * If `nbinsx` is provided, we choose a nice round bin size + * giving no more than that many bins. For date data, + * use milliseconds or "M" for months, as in `axis.dtick`. + * For category data, the number of categories to bin together + * (always defaults to 1). + */ + public var size: Number by numberGreaterThan(0) + + public companion object : SchemeSpec(::Bins) +} + +public enum class HistogramDirection { + increasing, + decreasing +} + +public enum class CurrentBin { + include, + exclude, + half +} + +public class Cumulative : Scheme() { + /** + * If true, display the cumulative distribution by summing + * the binned values. Use the `direction` and `centralbin` + * attributes to tune the accumulation method. Note: in this mode, + * the "density" `histnorm` settings behave the same + * as their equivalents without "density": "" and "density" + * both rise to the number of data points, and "probability" + * and "probability density" both rise to the number of sample points. + */ + public var enabled: Boolean? by boolean() + + /** + * Enumerated , one of ( "include" | "exclude" | "half" ) + * Only applies if cumulative is enabled. Sets whether the current bin + * is included, excluded, or has half of its value included in + * the current cumulative value. "include" is the default for + * compatibility with various other tools, however it introduces + * a half-bin bias to the results. "exclude" makes the opposite + * half-bin bias, and "half" removes it. + * Default: include. + */ + public var currentbin: CurrentBin by enum(CurrentBin.include) + + public companion object : SchemeSpec(::Cumulative) +} + + +public open class Histogram : Trace() { + init { + type = TraceType.histogram + } + + /** + * Enumerated, one of ( "empty" | "percent" | "probability" | "density" | "probability density" ) + * Specifies the type of normalization used for this histogram trace. + * If "empty", the span of each bar corresponds to the number of occurrences + * (i.e. the number of data points lying inside the bins). If "percent" / "probability", + * the span of each bar corresponds to the percentage / fraction of occurrences + * with respect to the total number of sample points (here, the sum of all + * bin HEIGHTS equals 100% / 1). If "density", the span of each bar corresponds + * to the number of occurrences in a bin divided by the size of the bin interval + * (here, the sum of all bin AREAS equals the total number of sample points). + * If "probability density", the area of each bar corresponds to the probability + * that an event will fall into the corresponding bin (here, the sum of all bin AREAS equals 1). + * Default: "empty". + */ + public var histnorm: HistNorm by enum(HistNorm.empty) + + /** + * Enumerated , one of ( "count" | "sum" | "avg" | "min" | "max" ) + * Specifies the binning function used for this histogram trace. + * If "count", the histogram values are computed by counting the + * number of values lying inside each bin. If "sum", "avg", "min", "max", + * the histogram values are computed using the sum, the average, + * the minimum or the maximum of the values lying inside each bin respectively. + * Default: "count" + */ + public var histfunc: HistFunc by enum(HistFunc.count) + + /** + * Enumerated , one of ( "increasing" | "decreasing" ) + * Only applies if cumulative is enabled. If "increasing" (default) + * we sum all prior bins, so the result increases from left to right. + * If "decreasing" we sum later bins so the result decreases from left to right. + * Default: increasing. + */ + public var direction: HistogramDirection by enum(HistogramDirection.increasing) + + public var cumulative: Cumulative by scheme(Cumulative) + + public var xbins: Bins by scheme(Bins) + + public var ybins: Bins by scheme(Bins) + + /** + * Specifies the maximum number of desired bins. This value will be used in an algorithm + * that will decide the optimal bin size such that the histogram best visualizes the + * distribution of the data. Ignored if `xbins.size` is provided. + */ + public var nbinsx: Int by intGreaterThan(0) + + /** + * Specifies the maximum number of desired bins. This value will be used in an algorithm + * that will decide the optimal bin size such that the histogram best visualizes the + * distribution of the data. Ignored if `ybins.size` is provided. + */ + public var nbinsy: Int by intGreaterThan(0) + + /** + * Set a group of histogram traces which will have compatible bin settings. + * Note that traces on the same subplot and with the same "orientation" under + * `barmode` "stack", "relative" and "group" are forced into the same bingroup, + * Using `bingroup`, traces under `barmode` "overlay" and on different axes + * (of the same axis type) can have compatible bin settings. Note that histogram + * and histogram2d" trace can share the same `bingroup`. + * Default: "". + */ + public var bingroup: String? by string() + + /** + * Set a group of histogram traces which will have compatible x-bin settings. + * Using `xbingroup`, histogram2d and histogram2dcontour traces (on axes of the same axis type) + * can have compatible x-bin settings. Note that the same `xbingroup` value + * can be used to set (1D) histogram `bingroup` + */ + public var xbingroup: String? by string() + + /** + * Set a group of histogram traces which will have compatible x-bin settings. + * Using `ybingroup`, histogram2d and histogram2dcontour traces (on axes of the same axis type) + * can have compatible x-bin settings. Note that the same `ybingroup` value + * can be used to set (1D) histogram `bingroup` + */ + public var ybingroup: String? by string() + + public fun cumulative(block: Cumulative.() -> Unit) { + cumulative = Cumulative(block) + } + + public fun xbins(block: Bins.() -> Unit) { + xbins = Bins(block) + } + + public fun ybins(block: Bins.() -> Unit) { + ybins = Bins(block) + } + + public companion object : SchemeSpec(::Histogram) +} + +public class Histogram2D : Histogram(), Table2D { + init { + type = TraceType.histogram2d + } + + /** + * Sets the horizontal gap (in pixels) between bricks. + */ + override var xgap: Number by numberGreaterThan(0) + + /** + * Sets the vertical gap (in pixels) between bricks. + */ + override var ygap: Number by numberGreaterThan(0) + + /** + * Picks a smoothing algorithm use to smooth `z` data. + */ + override var zsmooth: ZsmoothType by enum(ZsmoothType.best) + + public companion object : SchemeSpec(::Histogram2D) +} + +public class Histogram2DContour : Histogram(), ContourSpec { + init { + type = TraceType.histogram2dcontour + } + + /** + * Sets the maximum number of contour levels. The actual number of contours + * will be chosen automatically to be less than or equal to the value of `ncontours`. + * Has an effect only if `autocontour` is "true" or if `contours.size` is missing. + * Default: 15. + */ + override var ncontours: Int by intGreaterThan(1) + + override var contours: Contours by scheme(Contours) + + /** + * Determines whether or not the contour level attributes are picked by an algorithm. + * If "true" (default), the number of contour levels can be set in `ncontours`. + * If "false", set the contour level attributes in `contours`. + */ + override var autocontour: Boolean? by boolean() + + public fun contours(block: Contours.() -> Unit) { + contours = Contours(block) + } + + public companion object : SchemeSpec(::Histogram2DContour) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Images.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Images.kt new file mode 100644 index 00000000..26a8343b --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Images.kt @@ -0,0 +1,130 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.doubleInRange + + +public enum class ImageLayer { + below, above +} + +public enum class ImageSizing { + fill, contain, stretch +} + +public enum class ImageXAnchor { + left, center, right +} + +public enum class ImageYAnchor { + top, middle, bottom +} + +public class Image : Scheme() { + /** + * Specifies whether images are drawn below or above traces. When `xref` and `yref` are both set to `paper`, + * image is drawn below the entire plot area. + */ + public var layer: ImageLayer by enum(ImageLayer.above) + + /** + * When used in a template, named items are created in the output figure in addition to any items the figure + * already has in this array. You can modify these items in the output figure by making your own item with + * `templateitemname` matching this `name` alongside your modifications (including `visible: false` or + * `enabled: false` to hide it). Has no effect outside of a template. + */ + public var name: String? by string() + + + /** + * Sets the opacity of the image. + */ + public var opacity: Double by doubleInRange(0.0..1.0, 0.0) + + /** + * Sets the image container size horizontally. The image will be sized based on the `position` value . + * When `xref` is set to `paper`, units are sized relative to the plot width. When `xref` ends with ` domain`, + * units are sized relative to the axis width. + */ + public var sizex: Double by double(0.0) + + + /** + * Sets the image container size vertically. The image will be sized based on the `position` value . + * When `yref` is set to `paper`, units are sized relative to the plot height. When `yref` ends with ` domain`, + * units are sized relative to the axis height. + */ + public var sizey: Double by double(0.0) + + + /** + * Specifies which dimension of the image to constrain. + */ + public var sizing: ImageSizing by enum(ImageSizing.contain) + + /** + * Specifies the URL of the image to be used. The URL must be accessible from the domain where the plot code is run, + * and can be either relative or absolute. + */ + public var source: String? by string() + + /** + * Used to refer to a named item in this array in the template. Named items from the template will be created even + * without a matching item in the input figure, but you can modify one by making an item with `templateitemname` + * matching its `name`, alongside your modifications (including `visible: false` or `enabled: false` to hide it). + * If there is no template or no matching item, this item will be hidden unless you explicitly show it with `visible: true`. + */ + public var templateitemname: String? by string() + + /** + * Determines whether this image is visible. + */ + public var visible: Boolean by boolean(true) + + + /** + * Sets the image's x position. When `xref` is set to `paper`, units are sized relative to the plot height. See `xref` for more info + */ + public var x: Double by double(0.0) + + + /** + * Sets the anchor for the x position + */ + public var xanchor: ImageXAnchor by enum(ImageXAnchor.left) + + + /** + * Sets the images's x coordinate axis. If set to a x axis id (e.g. "x" or "x2"), the `x` position refers to + * a x coordinate. If set to "paper", the `x` position refers to the distance from the left of the plotting + * area in normalized coordinates where "0" ("1") corresponds to the left (right). If set to a x axis ID followed + * by "domain" (separated by a space), the position behaves like for "paper", but refers to the distance in fractions + * of the domain length from the left of the domain of that axis: e.g., "x2 domain" refers to the domain of the + * second x axis and a x position of 0.5 refers to the point between the left and the right of the domain of the second x axis. + */ + public var xref: String by string("paper") + + /** + * Sets the image's y position. When `yref` is set to `paper`, units are sized relative to the plot height. See `yref` for more info + */ + public var y: Double by double(0.0) + + /** + * Sets the anchor for the y position. + */ + public var yanchor: ImageYAnchor by enum(ImageYAnchor.top) + + /** + * Sets the images's y coordinate axis. If set to a y axis id (e.g. "y" or "y2"), the `y` position refers to a y + * coordinate. If set to "paper", the `y` position refers to the distance from the bottom of the plotting area in + * normalized coordinates where "0" ("1") corresponds to the bottom (top). If set to a y axis ID followed by "domain" + * (separated by a space), the position behaves like for "paper", but refers to the distance in fractions of the + * domain length from the bottom of the domain of that axis: e.g., "y2 domain" refers to the domain of the second + * y axis and a y position of 0.5 refers to the point between the bottom and the top of the domain of the second y axis. + */ + public var yref: String by string("paper") + + public companion object : SchemeSpec(::Image) { + + } +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Layout.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Layout.kt new file mode 100644 index 00000000..ae8e3145 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Layout.kt @@ -0,0 +1,348 @@ +@file:Suppress("EnumEntryName") +@file:OptIn(DFExperimental::class) + +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.meta.set +import space.kscience.dataforge.misc.DFExperimental +import space.kscience.dataforge.names.asName +import space.kscience.plotly.appendAndAttach +import space.kscience.plotly.numberGreaterThan +import space.kscience.plotly.numberInRange +import kotlin.js.JsName + + +public enum class BarMode { + stack, + group, + overlay, + relative +} + +public class Margin : Scheme() { + /** + * Turns on/off margin expansion computations. Legends, colorbars, updatemenus, sliders, + * axis rangeselector and rangeslider are allowed to push the margins by defaults. + */ + public var autoexpand: Boolean? by boolean() + + /** + * Sets the amount of padding (in px) between the plotting area and the axis lines + */ + public var pad: Number by numberGreaterThan(0) + + /** + * Sets the left margin (in px). Default: 80. + */ + public var l: Number by numberGreaterThan(0) + + /** + * Sets the right margin (in px). Default: 80. + */ + public var r: Number by numberGreaterThan(0) + + /** + * Sets the top margin (in px). Default: 100. + */ + public var t: Number by numberGreaterThan(0) + + /** + * Sets the bottom margin (in px). Default: 80. + */ + public var b: Number by numberGreaterThan(0) + + public companion object : SchemeSpec(::Margin) +} + +public enum class BoxMode { + overlay, + group +} + +public enum class HoverMode { + x, + y, + closest, + `false`, + + @JsName("xUnified") + `x unified`, + + @JsName("yUnified") + `y unified` +} + +public enum class BarNorm { + fraction, + percent, + + @Suppress("DANGEROUS_CHARACTERS") + @JsName("empty") + `""` +} + +public enum class ViolinMode { + group, + overlay +} + +public enum class DragMode { + zoom, pan, select, lasso, drawclosedpath, drawopenpath, drawline, drawrect, drawcircle, orbit, turntable, `false` +} + +public class Layout : Scheme() { + /** + * Sets the plot's width (in px). + * Number greater than or equal to 10, default: 700. + */ + public var width: Number by numberGreaterThan(10) + + /** + * Sets the plot's height (in px). + * Number greater than or equal to 10, default: 450. + */ + public var height: Number by numberGreaterThan(10) + + /** + * Determines whether or not a layout width or height that has been left undefined + * by the user is initialized on each relayout. Note that, regardless of this attribute, an undefined layout + * width or height is always initialized on the first call to plot. + */ + public var autosize: Boolean? by boolean() + + /** + * Sets the plot's title. + */ + public var title: String? + get() = meta["title.text"].string ?: meta["title"].string + set(value) { + meta["title.text"] = value?.asValue() + } + + public var xaxis: Axis by scheme(Axis) + + public var yaxis: Axis by scheme(Axis) + + /** + * Enumerated, one of ( "stack" | "group" | "overlay" | "relative" ) + * Determines how bars at the same location coordinate + * are displayed on the graph. With "stack", the bars + * are stacked on top of one another With "relative", + * the bars are stacked on top of one another, with negative values + * below the axis, positive values above With "group", the bars + * are plotted next to one another centered around the shared location. + * With "overlay", the bars are plotted over one another, you might + * need to an "opacity" to see multiple bars. + * Default: "group". + */ + public var barmode: BarMode by enum(BarMode.group) + + /** + * Sets the normalization for bar traces on the graph. With "fraction", the value of each bar + * is divided by the sum of all values at that location coordinate. "percent" is the same but multiplied + * by 100 to show percentages. Default: "". + */ + public var barnorm: BarNorm by enum(BarNorm.`""`) + + /** + * Sets the gap (in plot fraction) between bars + * of adjacent location coordinates. + */ + public var bargap: Number by numberInRange(0.0..1.0) + + /** + * Sets the gap (in plot fraction) between bars of the same location coordinate. + * Default: 0. + */ + public var bargroupgap: Number by numberInRange(0.0..1.0) + + /** + * Determines how violins at the same location coordinate are displayed on the graph. If "group", + * the violins are plotted next to one another centered around the shared location. If "overlay", + * the violins are plotted over one another, you might need to set "opacity" to see them multiple violins. + * Has no effect on traces that have "width" set. + */ + public var violinmode: ViolinMode by enum(ViolinMode.overlay) + + /** + * Sets the gap (in plot fraction) between violins of adjacent location coordinates. + * Has no effect on traces that have "width" set. Default: 0.3 + */ + public var violingap: Number by numberInRange(0.0..1.0) + + /** + * Sets the gap (in plot fraction) between violins of the same location coordinate. + * Has no effect on traces that have "width" set. Default: 0.3 + */ + public var violingroupgap: Number by numberInRange(0.0..1.0) + + public var legend: Legend by scheme(Legend) + + /** + * An annotation is a text element that can be placed anywhere in the plot. + * It can be positioned with respect to relative coordinates in the plot + * or with respect to the actual data coordinates of the graph. + * Annotations can be shown with or without an arrow. + */ + public var annotations: List by listOfScheme(Text) + + public var shapes: List by listOfScheme(Shape) + + /** + * Sets the background color of the paper where the graph is drawn. + * Default: #fff. + */ + public val paper_bgcolor: Color by color() + + /** + * Sets the background color of the plotting area in-between x and y axes. + * Default: #fff. + */ + public val plot_bgcolor: Color by color() + + public var margin: Margin by scheme(Margin) + + /** + * Determines how boxes at the same location coordinate are displayed on the graph. If "group", + * the boxes are plotted next to one another centered around the shared location. If "overlay", + * the boxes are plotted over one another, you might need to set "opacity" to see them multiple boxes. + * Has no effect on traces that have "width" set. + */ + public var boxmode: BoxMode by enum(BoxMode.overlay) + + /** + * Sets the gap (in plot fraction) between boxes of adjacent location coordinates. + * Has no effect on traces that have "width" set. Default: 0.3 + */ + public var boxgap: Number by numberInRange(0.0..1.0) + + /** + * Sets the gap (in plot fraction) between boxes of the same location coordinate. + * Has no effect on traces that have "width" set. Default: 0.3 + */ + public var boxgroupgap: Number by numberInRange(0.0..1.0) + + /** + * Determines whether or not a legend is drawn. Default is `true` if there is a trace to show and any of these: + * a) Two or more traces would by default be shown in the legend. + * b) One pie trace is shown in the legend. + * c) One trace is explicitly given with `showlegend: true`. + */ + public var showlegend: Boolean? by boolean() + + /** + * Determines the mode of hover interactions. If "closest", a single hoverlabel will appear for the "closest" + * point within the `hoverdistance`. If "x" (or "y"), multiple hoverlabels will appear for multiple points + * at the "closest" x- (or y-) coordinate within the `hoverdistance`, with the caveat that no more than one + * hoverlabel will appear per trace. If "x unified" (or "y unified"), a single hoverlabel will appear + * multiple points at the closest x- (or y-) coordinate within the `hoverdistance` with the caveat that + * no more than one hoverlabel will appear per trace. In this mode, spikelines are enabled by + * default perpendicular to the specified axis. If false, hover interactions are disabled. If `clickmode` includes + * the "select" flag, `hovermode` defaults to "closest". If `clickmode` lacks the "select" flag, it defaults + * to "x" or "y" (depending on the trace's `orientation` value) for plots based on cartesian coordinates. + * For anything else the default value is "closest". + */ + public var hovermode: HoverMode by enum(HoverMode.closest) + + /** + * Sets the decimal and thousand separators. For example, ". " puts a '.' before decimals and a space + * between thousands. In English locales, dflt is ".," but other locales may alter this default. + */ + public var separators: String? by string() + + /** + * Sets the default distance (in pixels) to look for data to add hover labels (-1 means no cutoff, + * 0 means no looking for data). This is only a real distance for hovering on point-like objects, like + * scatter points. For area-like objects (bars, scatter fills, etc) hovering is on inside the area and off outside, + * but these objects will not supersede hover on point-like objects in case of conflict. + * Default: 20. + */ + public var hoverdistance: Number by numberGreaterThan(-1) + + /** + * Sets the default calendar system to use for interpreting and displaying dates throughout the plot. + */ + public var calendar: Calendar by enum(Calendar.gregorian) + + /** + * Determines the mode of drag interactions. "select" and "lasso" apply only to scatter traces with markers or text. + * "orbit" and "turntable" apply only to 3D scenes. + */ + public var dragmode: DragMode by enum(DragMode.zoom) + + public fun legend(block: Legend.() -> Unit) { + legend.apply(block) + } + + public fun title(block: Title.() -> Unit) { + Title.write(meta.getOrCreate("title")).apply(block) + } + + //TODO moe title to parameter block + public fun xaxis(block: Axis.() -> Unit) { + xaxis.apply(block) + } + + public fun yaxis(block: Axis.() -> Unit) { + yaxis.apply(block) + } + + /** + * Secondary y-axis. [index] must be 2 or more + */ + public fun yaxis(index: Int, block: Axis.() -> Unit) { + require(index >= 2) { "Secondary axis index must be 2 or more" } + val axisSpec by scheme(Axis, "yaxis$index".asName()) + axisSpec.apply(block) + } + + /** + * Add a [Text] annotation to layout + */ + public fun annotation(an: Text) { + meta.appendAndAttach("annotations", an.meta) + } + + /** + * Add a [Text] annotation to layout + */ + public fun annotation(anBuilder: Text.() -> Unit) { + annotation(Text(anBuilder)) + } + + /** + * Add a [Shape] to layout + */ + public fun figure(sh: Shape) { + meta.appendAndAttach("shapes", sh.meta) + } + + /** + * Add a [Shape] to layout + */ + public fun figure(shBuilder: Shape.() -> Unit) { + figure(Shape(shBuilder)) + } + + /** + * Add an image to the layout + */ + public fun image(image: Image) { + meta.appendAndAttach("images", image.meta) + } + + /** + * Add an image to the layout + */ + public fun image(block: Image.() -> Unit) { + image(Image(block)) + } + + public fun margin(block: Margin.() -> Unit) { + margin = Margin(block) + } + + public companion object : SchemeSpec(::Layout) +} + diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/LayoutLine.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/LayoutLine.kt new file mode 100644 index 00000000..7181b4fc --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/LayoutLine.kt @@ -0,0 +1,65 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.Scheme +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.dataforge.meta.enum +import space.kscience.dataforge.meta.numberList +import space.kscience.dataforge.names.asName +import space.kscience.plotly.numberGreaterThan +import space.kscience.plotly.numberInRange + +public enum class LineShape { + hv, + vh, + hvh, + vhv, + spline, + linear +} + +public enum class Dash { + solid, + dot, + dash, + longdash, + dashdot, + longdashdot +} + +public class LayoutLine : Scheme(), Line { + /** + * Sets the line color. + */ + override val color: Color by color() + + /** + * Sets the line width (in px). Default: 2. + */ + override var width: Number by numberGreaterThan(0) + + /** + * Sets the width (in px) of the lines bounding the marker points. + */ + override var widthList: List by numberList(key = "width".asName()) + + /** + * Determines the line shape. With "spline" the lines + * are drawn using spline interpolation. The other + * available values correspond to step-wise line shapes. + * Default: "linear" + */ + public var shape: LineShape by enum(LineShape.linear) + + /** + * Sets the style of the lines. + */ + public var dash: Dash by enum(Dash.solid) + + /** + * Sets the amount of smoothing for the contour lines, where "0" corresponds to no smoothing. + * Default: 1. + */ + public var smoothing: Number by numberInRange(0.0..1.3) + + public companion object : SchemeSpec(::LayoutLine) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Legend.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Legend.kt new file mode 100644 index 00000000..9742c8fa --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Legend.kt @@ -0,0 +1,120 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.Scheme +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.dataforge.meta.enum +import space.kscience.dataforge.meta.scheme +import space.kscience.plotly.numberGreaterThan +import space.kscience.plotly.numberInRange +import kotlin.js.JsName + +public enum class LegendOrientation { + @JsName("v") + vertical, + + @JsName("h") + horizontal +} + +public enum class XAnchor { + auto, + left, + center, + right +} + +public enum class YAnchor { + auto, + top, + middle, + bottom +} + +public enum class TraceOrder { + normal, + reversed +} + +public class Legend : Scheme() { + /** + * Sets the legend background color. Defaults to `paper_bgcolor`. + */ + public val bgcolor: Color by color() + + /** + * Sets the color of the border enclosing the legend. + * Default: #444. + */ + public val bordercolor: Color by color() + + /** + * Sets the width (in px) of the border enclosing the legend. + * Default: 0. + */ + public var borderwidth: Number by numberGreaterThan(0) + + /** + * Number between or equal -2 and 3. + * Sets the x position (in normalized coordinates) of the legend. + * Defaults to "1.02" for vertical legends and + * defaults to "0" for horizontal legends. + */ + public var x: Number by numberInRange(-2.0..3.0) + + /** + * Sets the legend's horizontal position anchor. + * This anchor binds the `x` position to the "left", + * "center" or "right" of the legend. Value "auto" + * anchors legends to the right for `x` values + * greater than or equal to 2/3, anchors legends + * to the left for `x` values less than or equal to 1/3 + * and anchors legends with respect to their center otherwise. + * Default: left. + */ + public var xanchor: XAnchor by enum(XAnchor.left) + + /** + * Number between or equal to -2 and 3. + * Sets the y position (in normalized coordinates) of the legend. + * Defaults to "1" for vertical legends, defaults to "-0.1" + * for horizontal legends on graphs w/o range sliders and + * defaults to "1.1" for horizontal legends on graph + * with one or multiple range sliders. + */ + public var y: Number by numberInRange(-2.0..3.0) + + /** + * Sets the legend's vertical position anchor. + * This anchor binds the `y` position to the "top", "middle" + * or "bottom" of the legend. Value "auto" anchors legends + * at their bottom for `y` values less than or equal to 1/3, + * anchors legends to at their top for `y` values + * greater than or equal to 2/3 and anchors legends + * with respect to their middle otherwise. + */ + public var yanchor: YAnchor by enum(YAnchor.auto) + + /** + * Sets the font used to text the legend items. + */ + public var font: Font by scheme(Font) + + /** + * Sets the orientation of the legend (vertical/horizontal). + * Default: vertical. + */ + public var orientation: LegendOrientation by enum(LegendOrientation.vertical) + + /** + * The order at which the legend items are displayed. + * "normal": top-to-bottom in the same order as the input data. + * "reversed": the items are displayed in the opposite order. + */ + public var traceorder: TraceOrder by enum(TraceOrder.normal) + + public fun font(block: Font.() -> Unit) { + font = Font(block) + } + + public companion object : SchemeSpec(::Legend) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Line.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Line.kt new file mode 100644 index 00000000..5a49b459 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Line.kt @@ -0,0 +1,9 @@ +package space.kscience.plotly.models + +public interface Line { + public val color: Color? + + public var width: Number + + public var widthList: List +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Marker.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Marker.kt new file mode 100644 index 00000000..315755b7 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Marker.kt @@ -0,0 +1,149 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.asName +import space.kscience.plotly.intGreaterThan +import space.kscience.plotly.listOfValues +import space.kscience.plotly.numberGreaterThan +import space.kscience.plotly.numberInRange + +public enum class GradientType { + radial, + horizontal, + vertical, + none +} + +public class Gradient : Scheme() { + /** + * Sets the final color of the gradient fill: the center color for radial, + * the right for horizontal, or the bottom for vertical. + */ + public val color: Color by color() + + /** + * Sets the type of gradient used to fill the markers + */ + public var type: GradientType by enum(GradientType.none) + + /** + * Sets the type of gradient used to fill the markers + */ + public var typesList: List by listOfValues() + + public fun colors(colors: Iterable) { + color.value = colors.map { Value.of(it) }.asValue() + } + + public fun typesList(array: Iterable) { + typesList = array.map { Value.of(it) } + } + + public companion object : SchemeSpec(::Gradient) +} + +public class Marker : Scheme() { + /** + * Sets the marker symbol type. + * Default: circle. + */ + public var symbol: Symbol by enum(Symbol.circle) + + /** + * Array of enumerateds. Sets the marker symbol type. + */ + public var symbolsList: List by listOfValues(key = "symbol".asName()) + + /** + * Sets the marker size (in px). + * Default: 6. + */ + public var size: Number by numberGreaterThan(0) + + /** + * Array of numbers greater than or equal to 0. + * Sets the markers size. Default: 6. + */ + public var sizesList: List by numberList(key = "size".asName()) + + /** + * Sets the marker opacity. + */ + public var opacity: Number by numberInRange(0.0..1.0) + + /** + * Sets the markers opacity. + */ + public var opacitiesList: List by numberList(key = "opacity".asName()) + + /** + * Sets a maximum number of points to be drawn on the graph. + * "0" corresponds to no limit. + * Default: 0. + */ + public var maxdisplayed: Int by intGreaterThan(0) + + /** + * Has an effect only if `size` is set to a numerical array. + * Sets the scale factor used to determine the rendered size + * of marker points. Use with `sizemin` and `sizemode`. + * Default: 1. + */ + public var sizeref: Number? by number() + + /** + * Has an effect only if `marker.size` is set to a numerical array. + * Sets the minimum size (in px) of the rendered marker points. + * Default: 0. + */ + public var sizemin: Number by numberGreaterThan(0) + + /** + * Enumerated , one of ( "diameter" | "area" ) + * Has an effect only if `marker.size` is set to a numerical array. + * Sets the rule for which the data in `size` is converted to pixels. + * Default: "diameter". + */ + public var sizemode: SizeMode by enum(SizeMode.diameter) + + public var line: MarkerLine by scheme(MarkerLine) + + /** + * Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale + * relative to the max and min values of the array or relative to `marker.cmin` and `marker.cmax` if set. + */ + public val color: Color by color() + + /** + * Sets the color of each sector. If not specified, the default trace color set is used to pick the sector colors. + */ + public var pieColors: List by listOfValues(key = "colors".asName()) + + public var colorbar: ColorBar by scheme(ColorBar) + + public var gradient: Gradient by scheme(Gradient) + + /** + * Sets the color of the outlier sample points. Default: rgba(0, 0, 0, 0). + */ + public val outliercolor: Color by color() + + public fun colors(colors: Iterable) { + color.value = colors.map { Value.of(it) }.asValue() + } + + public fun line(block: MarkerLine.() -> Unit) { + line = MarkerLine(block) + } + + public fun colorbar(block: ColorBar.() -> Unit) { + colorbar = ColorBar(block) + } + + public fun gradient(block: Gradient.() -> Unit) { + gradient = Gradient(block) + } + + public companion object : SchemeSpec(::Marker) +} + diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Pie.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Pie.kt new file mode 100644 index 00000000..c151fc0e --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Pie.kt @@ -0,0 +1,114 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.asName +import space.kscience.plotly.numberInRange +import kotlin.js.JsName + +public enum class PieDirection { + clockwise, + counterclockwise +} + +public enum class TextInfo { + label, + text, + value, + percent, + none, + + @JsName("labelText") + `label+text`, + + @JsName("labelValue") + `label+value`, + + @JsName("labelPercent") + `label+percent`, + + @JsName("textValue") + `text+value`, + + @JsName("textPercent") + `text+percent`, + + @JsName("valuePercent") + `value+percent`, + + @JsName("labelTextValue") + `label+text+value`, + + @JsName("labelTextPercent") + `label+text+percent`, + + @JsName("labelValuePercent") + `label+value+percent`, + + @JsName("textValuePercent") + `text+value+percent`, + + @JsName("labelTextValuePercent") + `label+text+value+percent` +} + +public class Pie : Trace() { + init { + type = TraceType.pie + } + + /** + * Sets the fraction of larger radius to pull the sectors out from the center. + * This is a constant to pull all slices apart from each other. + * Default: 0. + */ + public var pull: Number? by number() + + /** + * Sets the fraction of larger radius to pull the sectors out from the center. + * This is an array to highlight one or more slices. + */ + public var pullList: List by numberList(key = "pull".asName()) + + /** + * Specifies the direction at which succeeding sectors follow one another. + */ + public var direction: PieDirection by enum(PieDirection.counterclockwise) + + /** + * Sets the fraction of the radius to cut out of the pie. + * Use this to make a donut chart. Default: 0. + */ + public var hole: Number by numberInRange(0.0..1.0) + + /** + * Instead of the first slice starting at 12 o'clock, rotate to some other angle. + * Default: 0. + */ + public var rotation: Number by numberInRange(-360.0..360.0) + + /** + * Determines whether or not the sectors are reordered from largest to smallest. + * Default: true. + */ + public var sort: Boolean? by boolean() + + /** + * Sets the label step. See `label0` for more info. + * Default: 1. + */ + public var dlabel: Number? by number() + + /** + * Alternate to `labels`. Builds a numeric set of labels. + * Use with `dlabel` where `label0` is the starting label and `dlabel` the step. + * Default: 0. + */ + public var label0: Number? by number() + + /** + * Determines which trace information appear on the graph. + */ + public var textinfo: TextInfo by enum(TextInfo.percent) + + public companion object : SchemeSpec(::Pie) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Scatter.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Scatter.kt new file mode 100644 index 00000000..8e85accc --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Scatter.kt @@ -0,0 +1,158 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import kotlin.js.JsName + +public enum class ScatterMode { + lines, + markers, + text, + none, + + @JsName("linesMarkers") + `lines+markers`, + + @JsName("linesText") + `lines+text`, + + @JsName("markersText") + `markers+text`, + + @JsName("linesMarkersText") + `lines+markers+text` +} + +public enum class GroupNorm { + @JsName("empty") + ` `, + fraction, + percent +} + +public enum class FillType { + none, + tozeroy, + tozerox, + tonexty, + tonextx, + toself, + tonext +} + +public enum class ScatterHoveron { + points, + fills, + + @JsName("pointsAndFills") + `points+fills` +} + +public enum class StackGaps { + @JsName("inferZero") + `infer zero`, + interpolate +} + +public open class Scatter : Trace(), SelectedPoints { + init { + type = TraceType.scatter + } + + /** + * Flaglist string. Any combination of "lines", "markers", "text" + * joined with a "+" OR "none". Determines the drawing mode for + * this scatter trace. If the provided `mode` includes "text" then + * the `text` elements appear at the coordinates. Otherwise, + * the `text` elements appear on hover. + * Default: lines. + */ + public var mode: ScatterMode by enum(ScatterMode.lines) + + /** + * Only relevant when `stackgroup` is used, and only the first `groupnorm` found in the `stackgroup` will be used - + * including if `visible` is "legendonly" but not if it is `false`. Sets the normalization for the sum of + * this `stackgroup`. With "fraction", the value of each trace at each location is divided by the sum of all + * trace values at that location. "percent" is the same but multiplied by 100 to show percentages. If there are + * multiple subplots, or multiple `stackgroup`s on one subplot, each will be normalized within its own set. + */ + public var groupnorm: GroupNorm by enum(GroupNorm.` `) + + /** + * Set several scatter traces (on the same subplot) to the same stackgroup in order to add their + * y values (or their x values if `orientation` is "h"). If blank or omitted this trace will not be stacked. + * Stacking also turns `fill` on by default, using "tonexty" ("tonextx") if `orientation` is "h" ("v") + * and sets the default `mode` to "lines" irrespective of point count. You can only stack on a numeric + * (linear or log) axis. Traces in a `stackgroup` will only fill to (or be filled to) other traces in the + * same group. With multiple `stackgroup`s or some traces stacked and some not, if fill-linked traces are + * not already consecutive, the later ones will be pushed down in the drawing order. + * Default: "". + */ + public var stackgroup: String? by string() + + /** + * Array containing integer indices of selected points. Has an effect only for traces that support selections. + * Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, + * any other non-array values means no selection all where the `selected` and `unselected` styles have no effect. + */ + override var selectedpoints: List by numberList() + + override var selected: SelectPoints by scheme(SelectPoints) + + override var unselected: SelectPoints by scheme(SelectPoints) + + /** + * Sets the area to fill with a solid color. Defaults to "none" unless this trace is stacked, then + * it gets "tonexty" ("tonextx") if `orientation` is "v" ("h") Use with `fillcolor` if not "none". + * "tozerox" and "tozeroy" fill to x=0 and y=0 respectively. "tonextx" and "tonexty" fill between + * the endpoints of this trace and the endpoints of the trace before it, connecting those endpoints + * with straight lines (to make a stacked area graph); if there is no trace before it, they behave + * like "tozerox" and "tozeroy". "toself" connects the endpoints of the trace (or each segment + * of the trace if it has gaps) into a closed shape. "tonext" fills the space between two traces + * if one completely encloses the other (eg consecutive contour lines), and behaves like "toself" + * if there is no trace before it. "tonext" should not be used if one trace does not enclose the other. + * Traces in a `stackgroup` will only fill to (or be filled to) other traces in the same group. + * With multiple `stackgroup`s or some traces stacked and some not, if fill-linked traces + * are not already consecutive, the later ones will be pushed down in the drawing order. + */ + public var fill: FillType by enum(FillType.none) + + /** + * Do the hover effects highlight individual points (markers or line points) or do they + * highlight filled regions? If the fill is "toself" or "tonext" and there are no markers or text, + * then the default is "fills", otherwise it is "points". + */ + public var hoveron: ScatterHoveron by enum(ScatterHoveron.points) + + /** + * Only relevant when `stackgroup` is used, and only the first `stackgaps` found in the `stackgroup` + * will be used - including if `visible` is "legendonly" but not if it is `false`. Determines how + * we handle locations at which other traces in this group have data but this one does not. + * With "infer zero" we insert a zero at these locations. With "interpolate" we linearly interpolate + * between existing values, and extrapolate a constant beyond the existing values. + */ + public var stackgaps: StackGaps by enum(StackGaps.`infer zero`) + + /** + * Sets a reference between this trace's y coordinates and a 2D cartesian y axis. If "y" (the default value), + * the y coordinates refer to `layout.yaxis`. If "y2", the y coordinates refer to `layout.yaxis2`, and so on. + */ + public var yaxis: String by string("y") + + public fun selected(block: SelectPoints.() -> Unit) { + selected = SelectPoints(block) + } + + public fun unselected(block: SelectPoints.() -> Unit) { + unselected = SelectPoints(block) + } + + public companion object : SchemeSpec(::Scatter) +} + +public class ScatterGL : Scatter() { + init { + type = TraceType.scattergl + } + + public companion object : SchemeSpec(::ScatterGL) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/SelectedPoints.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/SelectedPoints.kt new file mode 100644 index 00000000..56e660f0 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/SelectedPoints.kt @@ -0,0 +1,55 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.Scheme +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.dataforge.meta.scheme +import space.kscience.plotly.numberGreaterThan +import space.kscience.plotly.numberInRange + +public class SelectMarker : Scheme() { + /** + * Sets the marker opacity of selected points. + */ + public var opacity: Number by numberInRange(0.0..1.0) + + /** + * Sets the marker color of selected points. + */ + public val color: Color by color() + + /** + * Sets the marker size of selected points. + */ + public var size: Number by numberGreaterThan(0) + + public companion object : SchemeSpec(::SelectMarker) +} + +public class SelectPoints : Scheme() { + public var marker: SelectMarker by scheme(SelectMarker) + + public var textfont: Font by scheme(Font) + + public fun marker(block: SelectMarker.() -> Unit) { + marker = SelectMarker(block) + } + + public fun textfont(block: Font.() -> Unit) { + textfont = Font(block) + } + + public companion object : SchemeSpec(::SelectPoints) +} + +public interface SelectedPoints { + /** + * Array containing integer indices of selected points. Has an effect only for traces that support selections. + * Note that an empty array means an empty selection where the `unselected` are turned on for all points, whereas, + * any other non-array values means no selection all where the `selected` and `unselected` styles have no effect. + */ + public var selectedpoints: List + + public var selected: SelectPoints + + public var unselected: SelectPoints +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Shape.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Shape.kt new file mode 100644 index 00000000..a4a8990b --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Shape.kt @@ -0,0 +1,194 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.numberInRange + +public enum class ShapeType { + circle, + rect, + path, + line +} + +public enum class ShapeLayer { + below, + above +} + +public enum class ShapeSizeMode { + scaled, + pixel +} + +public enum class ShapeFillRule { + evenodd, + nonzero +} + +public class Shape : Scheme() { + /** + * Determines whether or not this shape is visible. + * Default: True + */ + public var visible: Boolean? by boolean() + + /** + * Specifies the shape type to be drawn. If "line", a line is drawn from (`x0`,`y0`) to (`x1`,`y1`) + * with respect to the axes' sizing mode. If "circle", a circle is drawn from ((`x0`+`x1`)/2, (`y0`+`y1`)/2)) + * with radius (|(`x0`+`x1`)/2 - `x0`|, |(`y0`+`y1`)/2 -`y0`)|) with respect to the axes' sizing mode. If "rect", + * a rectangle is drawn linking (`x0`,`y0`), (`x1`,`y0`), (`x1`,`y1`), (`x0`,`y1`), (`x0`,`y0`) with respect to the + * axes' sizing mode. If "path", draw a custom SVG path using `path`. with respect to the axes' sizing mode. + */ + public var type: ShapeType by enum(ShapeType.line) + + /** + * Specifies whether shapes are drawn below or above traces. + */ + public var layer: ShapeLayer by enum(ShapeLayer.above) + + /** + * Sets the shape's x coordinate axis. If set to an x axis id (e.g. "x" or "x2"), the `x` position refers + * to an x coordinate. If set to "paper", the `x` position refers to the distance from the left side of + * the plotting area in normalized coordinates where "0" ("1") corresponds to the left (right) side. + * If the axis `type` is "log", then you must take the log of your desired range. If the axis `type` is "date", + * then you must convert the date to unix time in milliseconds. + */ + public var xref: String? by string() + + /** + * Sets the shapes's sizing mode along the x axis. If set to "scaled", `x0`, `x1` and x coordinates + * within `path` refer to data values on the x axis or a fraction of the plot area's width (`xref` set to "paper"). + * If set to "pixel", `xanchor` specifies the x position in terms of data or plot fraction but `x0`, `x1` + * and x coordinates within `path` are pixels relative to `xanchor`. This way, the shape can have + * a fixed width while maintaining a position relative to data or plot fraction. Default: scaled. + */ + public var xsizemode: ShapeSizeMode by enum(ShapeSizeMode.scaled) + + /** + * Only relevant in conjunction with `xsizemode` set to "pixel". Specifies the anchor point on the x axis + * to which `x0`, `x1` and x coordinates within `path` are relative to. E.g. useful to attach + * a pixel sized shape to a certain data value. No effect when `xsizemode` not set to "pixel". + */ + public var xanchor: Value? by value() + + /** + * Sets the shape's starting x position. See `type` and `xsizemode` for more info. + */ + public var x0: Value? by value() + + /** + * Sets the shape's end x position. See `type` and `xsizemode` for more info. + */ + public var x1: Value? by value() + + /** + * Sets the annotation's y coordinate axis. If set to an y axis id (e.g. "y" or "y2"), the `y` position refers + * to an y coordinate If set to "paper", the `y` position refers to the distance from the bottom of + * the plotting area in normalized coordinates where "0" ("1") corresponds to the bottom (top). + */ + public var yref: String? by string() + + /** + * Sets the shapes's sizing mode along the y axis. If set to "scaled", `y0`, `y1` and y coordinates within + * `path` refer to data values on the y axis or a fraction of the plot area's height (`yref` set to "paper"). + * If set to "pixel", `yanchor` specifies the y position in terms of data or plot fraction but `y0`, `y1` + * and y coordinates within `path` are pixels relative to `yanchor`. This way, the shape can have a fixed height + * while maintaining a position relative to data or plot fraction. Default: scaled. + */ + public var ysizemode: ShapeSizeMode by enum(ShapeSizeMode.scaled) + + /** + * Only relevant in conjunction with `ysizemode` set to "pixel". Specifies the anchor point on the y axis + * to which `y0`, `y1` and y coordinates within `path` are relative to. E.g. useful to attach a pixel sized shape + * to a certain data value. No effect when `ysizemode` not set to "pixel". + */ + public var yanchor: Value? by value() + + /** + * Sets the shape's starting y position. See `type` and `ysizemode` for more info. + */ + public var y0: Value? by value() + + /** + * Sets the shape's end y position. See `type` and `ysizemode` for more info. + */ + public var y1: Value? by value() + + /** + * XY number position of the start + */ + public fun startXY(x: Number, y: Number) { + x0 = x.asValue() + y0 = y.asValue() + } + + /** + * XY number position of the end + */ + public fun endXY(x: Number, y: Number) { + x1 = x.asValue() + y1 = y.asValue() + } + + /** + * For `type` "path" - a valid SVG path with the pixel values replaced by data values in `xsizemode`/`ysizemode` + * being "scaled" and taken unmodified as pixels relative to `xanchor` and `yanchor` in case of "pixel" size mode. + * There are a few restrictions / quirks only absolute instructions, not relative. So the allowed segments are: + * M, L, H, V, Q, C, T, S, and Z arcs (A) are not allowed because radius rx and ry are relative. In the future + * we could consider supporting relative commands, but we would have to decide on how to handle date and log axes. + * Note that even as is, Q and C Bezier paths that are smooth on linear axes may not be smooth on log, and + * vice versa. no chained "polybezier" commands - specify the segment type for each one. On category axes, values + * are numbers scaled to the serial numbers of categories because using the categories themselves there would be + * no way to describe fractional positions On data axes: because space and T are both normal components of path + * strings, we can't use either to separate date from time parts. Therefore we'll use underscore for this purpose: + * 2015-02-21_13:45:56.789 + */ + public var path: String? by string() + + /** + * Sets the opacity of the shape. Default: 1. + */ + public var opacity: Number by numberInRange(0.0..1.0) + + public var line: LayoutLine by scheme(LayoutLine) + + /** + * Sets the color filling the shape's interior. Only applies to closed shapes. Default: rgba(0, 0, 0, 0) + */ + public val fillcolor: Color by color() + + /** + * Determines which regions of complex paths constitute the interior. Default: evenodd. + * For more info please visit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule + */ + public var fillrule: ShapeFillRule by enum(ShapeFillRule.evenodd) + + /** + * Determines whether the shape could be activated for edit or not. Has no effect + * when the older editable shapes mode is enabled via `config.editable` or `config.edits.shapePosition`. + */ + public var editable: Boolean? by boolean() + + /** + * When used in a template, named items are created in the output figure in addition to any items + * the figure already has in this array. You can modify these items in the output figure by making your own item + * with `templateitemname` matching this `name` alongside your modifications (including `visible: false` or + * `enabled: false` to hide it). Has no effect outside of a template. + */ + public var name: String? by string() + + /** + * Used to refer to a named item in this array in the template. Named items from the template will be created + * even without a matching item in the input figure, but you can modify one by making an item + * with `templateitemname` matching its `name`, alongside your modifications (including `visible: false` + * or `enabled: false` to hide it). If there is no template or no matching item, this item will be hidden + * unless you explicitly show it with `visible: true`. + */ + public var templateitemname: String? by string() + + public fun line(block: LayoutLine.() -> Unit) { + line = LayoutLine(block) + } + + public companion object : SchemeSpec(::Shape) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Table.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Table.kt new file mode 100644 index 00000000..c888f3a6 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Table.kt @@ -0,0 +1,215 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.asName +import space.kscience.plotly.numberGreaterThan + +/** + * Scheme to define table cell colors. + * */ +public class Fill : Scheme() { + + /** + * Sets the cell fill color. It accepts a specific color. + * */ + public var color: Color = Color(this, "color".asName()) + + /** + * Sets the cell fill color. It accepts an array of colors. + * */ + public fun colors(array: Iterable) { + color.value = array.map { Value.of(it) }.asValue() + } + + public companion object : SchemeSpec(::Fill) +} + +public class Header : Scheme() { + + /** + * Cell values. `values[m][n]` represents the value of the "n"-th point in column "m", therefore + * the `values[m]` vector length for all columns must be the same (longer vectors will be truncated). + * + * Each value must be a finite number or a string. + * */ + public var values: TraceValues = TraceValues(this, "values".asName()) + + /** + * The height of cells. + * */ + public var height: Number by numberGreaterThan(1) + + /** + * Sets the horizontal alignment of the `text` within the box. Has an effect only if `text` spans + * two or more lines (i.e. `text` contains one or more
HTML tags) or if an explicit width is set + * to override the text width. + * + * Defaults to `center`. + * */ + public var align: TraceValues = TraceValues(this, "align".asName()) + + /** + * [LayoutLine] type object. + * */ + public var line: LayoutLine by scheme(LayoutLine) + + /** + * [Fill] type object. + * */ + public var fill: Fill by scheme(Fill) + + /** + * [Font] type object. + * */ + public var font: Font by scheme(Font) + + public fun values(array: Iterable) { + values.set(array) + } + + public fun align(align: HorizontalAlign) { + align(listOf(align)) + } + + public fun align(alignments: List) { + this.align.set(alignments) + } + + public fun align(vararg alignments: HorizontalAlign) { + this.align.set(alignments.toList()) + } + + public fun fill(block: Fill.() -> Unit) { + fill = Fill(block) + } + + public fun font(block: Font.() -> Unit) { + font = Font(block) + } + + public companion object : SchemeSpec
(::Header) +} + +public class Cells : Scheme() { + + /** + * Cell values. `values[m][n]` represents the value of the "n"-th point in column "m", therefore + * the `values[m]` vector length for all columns must be the same (longer vectors will be truncated). + * + * Each value must be a finite number or a string. + * */ + public var values: TraceValues = TraceValues(this, "values".asName()) + + /** + * The height of cells. + * */ + public var height: Number by numberGreaterThan(1) + + /** + * Sets the horizontal alignment of the `text` within the box. Has an effect only if `text` spans + * two or more lines (i.e. `text` contains one or more
HTML tags) or if an explicit width is set + * to override the text width. + * + * Defaults to `center`. + * */ + public var align: TraceValues = TraceValues(this, "align".asName()) + + /** + * [LayoutLine] type object. + * */ + public var line: LayoutLine by scheme(LayoutLine) + + /** + * [Fill] type object. + * */ + public var fill: Fill by scheme(Fill) + + /** + * [Font] type object. + * */ + public var font: Font by scheme(Font) + + public fun values(array: Iterable) { + values.set(array) + } + + public fun align(align: HorizontalAlign) { + align(listOf(align)) + } + + public fun align(alignments: List) { + this.align.set(alignments) + } + + public fun align(vararg alignments: HorizontalAlign) { + this.align.set(alignments.toList()) + } + + public fun fill(block: Fill.() -> Unit) { + fill = Fill(block) + } + + public fun font(block: Font.() -> Unit) { + font = Font(block) + } + + public fun line(block: LayoutLine.() -> Unit) { + line = LayoutLine(block) + } + + public companion object : SchemeSpec(::Cells) +} + +/** + * Table view for detailed data viewing. The data are arranged in a grid of rows and columns. Most styling can + * be specified for columns, rows or individual cells. Table is using a column-major order, ie. the + * grid is represented as a vector of column vectors. + * + * For docs, see: [Plotly JS Table Reference](https://plotly.com/javascript/reference/table/#table) + * */ +public class Table : Trace() { + init { + type = TraceType.table + } + + /** + * Assigns id labels to each datum. These ids for object constancy of data points during animation. + * + * Should be an array of strings, not numbers or any other type. + * */ + public var ids: TraceValues = TraceValues(this, "ids".asName()) + + /** + * Specifies the rendered order of the data columns; for example, a value `2` at position `0` + * means that column index `0` in the data will be rendered as the third column, + * as columns have an index base of zero. + * */ + public var columnorder: TraceValues = TraceValues(this, "columnorder".asName()) + + + /** + * The width of columns expressed as a ratio. Columns fill the available width + * in proportion of their specified column widths. + * */ + public var columnwidth: TraceValues = TraceValues(this, "columnwidth".asName()) + + /** + * [Header] type object. Used to define the header row. + * */ + public var header: Header by scheme(Header) + + /** + * [Cells] type object. Used to define rows containing data. + * */ + public var cells: Cells by scheme(Cells) + + public fun header(block: Header.() -> Unit) { + header = Header(block) + } + + public fun cells(block: Cells.() -> Unit) { + cells = Cells(block) + } + + public companion object : SchemeSpec(::Table) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Table2D.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Table2D.kt new file mode 100644 index 00000000..67b108a6 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Table2D.kt @@ -0,0 +1,15 @@ +package space.kscience.plotly.models + +public enum class ZsmoothType { + fast, + best, + `false` +} + +public interface Table2D { + public var xgap: Number + + public var ygap: Number + + public var zsmooth: ZsmoothType +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Text.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Text.kt new file mode 100644 index 00000000..efe3ee76 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Text.kt @@ -0,0 +1,189 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.numberGreaterThan +import space.kscience.plotly.numberInRange + +public enum class HorizontalAlign { + left, + right, + center +} + +public enum class VerticalAlign { + top, + bottom, + middle +} + +/** + * Text annotation + */ +public class Text : Scheme() { + /** + * Determines whether or not this annotation is visible. + * Default: true + */ + public var visible: Boolean? by boolean() + + /** + * Sets the text associated with this annotation. + * Plotly uses a subset of HTML tags to do things + * like newline (
), bold (), italics (), + * hyperlinks (). Tags , , + * are also supported. + */ + public var text: String? by string() + + /** + * Sets the annotation text font. + */ + public var font: Font by scheme(Font) + + /** + * Sets the annotation's x position. If the axis `type` is "log", + * then you must take the log of your desired range. If the + * axis `type` is "date", it should be date strings, like date data, + * though Date objects and unix milliseconds will be accepted and + * converted to strings. If the axis `type` is "category", + * it should be numbers, using the scale where each category + * is assigned a serial number from zero in the order it appears. + */ + public var x: Value? by value() + + /** + * Sets the annotation's y position. If the axis `type` is "log", + * then you must take the log of your desired range. If the + * axis `type` is "date", it should be date strings, like date data, + * though Date objects and unix milliseconds will be accepted and + * converted to strings. If the axis `type` is "category", + * it should be numbers, using the scale where each category + * is assigned a serial number from zero in the order it appears. + */ + public var y: Value? by value() + + /** + * Sets an explicit width for the text box. null (default) lets the text set the box width. + * Wider text will be clipped. There is no automatic wrapping; use
to start a new line. + */ + public var width: Number by numberGreaterThan(1) + + /** + * Sets an explicit height for the text box. null (default) lets the text set the box height. + * Taller text will be clipped. + */ + public var height: Number by numberGreaterThan(1) + + /** + * Sets the opacity of the annotation (text + arrow). + */ + public var opacity: Number by numberInRange(0.0..1.0) + + /** + * Sets the background color of the annotation. + * Default: "rgba(0, 0, 0, 0)" + */ + public val bgcolor: Color by color() + + /** + * Sets the background color of the annotation. + * Default: "rgba(0, 0, 0, 0)" + */ + public val bordercolor: Color by color() + + /** + * Determines whether or not the annotation is drawn with an arrow. If "true", `text` + * is placed near the arrow's tail. If "false", `text` lines up with the `x` and `y` provided. + */ + public var showarrow: Boolean? by boolean() + + /** + * Sets the color of the annotation arrow. + */ + public val arrowcolor: Color by color() + + /** + * Sets the angle at which the `text` is drawn with respect to the horizontal. + */ + public var textangle: Number by numberInRange(-360.0..360.0) + + /** + * Sets a distance, in pixels, to move the end arrowhead away from the position + * it is pointing at, for example to point at the edge of a marker independent of zoom. + * Note that this shortens the arrow from the `ax` / `ay` vector, in contrast + * to `xshift` / `yshift` which moves everything by this amount. + */ + public var standoff: Number by numberGreaterThan(0) + + /** + * Sets the x component of the arrow tail about the arrow head. If `axref` is `pixel`, a positive (negative) + * component corresponds to an arrow pointing from right to left (left to right). If `axref` is an axis, + * this is an absolute value on that axis, like `x`, NOT a relative value. + */ + public var ax: Value? by value() + + /** + * Sets the y component of the arrow tail about the arrow head. If `ayref` is `pixel`, a positive (negative) + * component corresponds to an arrow pointing from bottom to top (top to bottom). If `ayref` is an axis, + * this is an absolute value on that axis, like `y`, NOT a relative value. + */ + public var ay: Value? by value() + + /** + * Sets the annotation's x coordinate axis. If set to an x axis id (e.g. "x" or "x2"), the `x` position refers + * to an x coordinate If set to "paper", the `x` position refers to the distance from the left side + * of the plotting area in normalized coordinates where 0 (1) corresponds to the left (right) side. + */ + public var xref: String? by string() + + /** + * Sets the annotation's y coordinate axis. If set to an y axis id (e.g. "y" or "y2"), the `y` position refers + * to an y coordinate If set to "paper", the `y` position refers to the distance from the bottom + * of the plotting area in normalized coordinates where 0 (1) corresponds to the bottom (top). + */ + public var yref: String? by string() + + /** + * Sets the horizontal alignment of the `text` within the box. Has an effect only if `text` spans two or more lines + * (i.e. `text` contains one or more
HTML tags) or if an explicit width is set to override the text width. + * Default: center. + */ + public var align: HorizontalAlign by enum(HorizontalAlign.center) + + /** + * Sets the vertical alignment of the `text` within the box. Has an effect only if an explicit height is set + * to override the text height. Default: middle. + */ + public var valign: VerticalAlign by enum(VerticalAlign.middle) + + /** + * Sets the text box's horizontal position anchor This anchor binds the `x` position to the "left", + * "center" or "right" of the annotation. For example, if `x` is set to 1, `xref` to "paper" and `xanchor` to + * "right" then the right-most portion of the annotation lines up with the right-most edge of the plotting area. + * If "auto", the anchor is equivalent to "center" for data-referenced annotations or if there is an arrow, + * whereas for paper-referenced with no arrow, the anchor picked corresponds to the closest side. + * Default: auto. + */ + public var xanchor: XAnchor by enum(XAnchor.auto) + + /** + * Sets the text box's vertical position anchor This anchor binds the `y` position to the "top", "middle" + * or "bottom" of the annotation. For example, if `y` is set to 1, `yref` to "paper" and `yanchor` to "top" then + * the top-most portion of the annotation lines up with the top-most edge of the plotting area. If "auto", + * the anchor is equivalent to "middle" for data-referenced annotations or if there is an arrow, whereas + * for paper-referenced with no arrow, the anchor picked corresponds to the closest side. + * Default: auto. + */ + public var yanchor: YAnchor by enum(YAnchor.auto) + + public fun position(x: Number, y: Number) { + this.x = x.asValue() + this.y = y.asValue() + } + + public fun font(block: Font.() -> Unit) { + font = Font(block) + } + + public companion object : SchemeSpec(::Text) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Trace.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Trace.kt new file mode 100644 index 00000000..36af015a --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Trace.kt @@ -0,0 +1,1024 @@ +@file:Suppress("PropertyName", "FunctionName") + +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.asName +import space.kscience.plotly.* +import kotlin.js.JsName +import kotlin.properties.ReadOnlyProperty + + +public enum class TraceType { + // Simple + scatter, + scattergl, + bar, + pie, + heatmap, + heatmapgl, + contour, + + table, + + @UnsupportedPlotlyAPI + image, + + // Distributions + box, + violin, + histogram, + histogram2d, + histogram2dcontour, + + // Finance + @UnsupportedPlotlyAPI + ohlc, + candlestick, + + @UnsupportedPlotlyAPI + waterfall, + + // 3D + scatter3d, + + surface, + + @UnsupportedPlotlyAPI + mesh3d, + + @UnsupportedPlotlyAPI + cone, + + @UnsupportedPlotlyAPI + streamtube, + + @UnsupportedPlotlyAPI + volume, + + @UnsupportedPlotlyAPI + isosurface, + + // Maps + scattergeo, + choropleth, + scattermapbox, + choroplethmapbox + // Specialized +} + +public enum class Visible { + `true`, + `false`, + legendonly +} + +public enum class Symbol { + circle, + + @JsName("triangleUp") + `triangle-up`, + + @JsName("triangleDown") + `triangle-down`, + + @JsName("squareCross") + `square-cross`, + + @JsName("crossThin") + `cross-thin`, + cross, + + @JsName("lineNs") + `line-ns` +} + +public enum class SizeMode { + diameter, + area +} + +public class MarkerLine : Scheme(), Line { + /** + * Number greater than or equal to 0. Sets the width (in px) + * of the lines bounding the marker points. + */ + override var width: Number by numberGreaterThan(0) + + /** + * Array of numbers greater than or equal to 0. Sets the width (in px) + * of the lines bounding the marker points. + */ + override var widthList: List by numberList(key = "width".asName()) + + /** + * Sets themarker.linecolor. It accepts either a specific color + * or an array of numbers that are mapped to the colorscale + * relative to the max and min values of the array or relative to + * `cmin` and `cmax` if set. + */ + override val color: Color by color() + + /** + * Determines whether or not the color domain is computed with respect + * to the input data (here in `color`) or the bounds set in `cmin` and `cmax` + * Has an effect only if in `color` is set to a numerical array. + * Defaults to `false` when `cmin` and `cmax` are set by the user. + * + */ + public var cauto: Boolean? by boolean() + + /** + * Sets the lower bound of the color domain. Has an effect only if + * in `color`is set to a numerical array. Value should have + * the same units as in `color` and if set, `cmax` must be set as well. + */ + public var cmin: Number? by number() + + /** + * Sets the upper bound of the color domain. Has an effect only if + * in `color`is set to a numerical array. Value should have + * the same units as in `color` and if set, `cmin` must be set as well. + */ + public var cmax: Number? by number() + + /** + * Sets the mid-point of the color domain by scaling `cmin` and/or `cmax` + * to be equidistant to this point. Has an effect only if in `color` + * is set to a numerical array. Value should have the same units + * as in `color`. Has no effect when `cauto` is `false`. + */ + public var cmid: Number? by number() + + /** + * Sets the colorscale. Has an effect only if in `color`is set to a numerical array. + * The colorscale must be an array containing arrays mapping a normalized value + * to an rgb, rgba, hex, hsl, hsv, or named color string. At minimum, + * a mapping for the lowest (0) and highest (1) values are required. For example, + * `[[0, 'rgb(0,0,255)'], [1, 'rgb(255,0,0)']]`. To control the bounds of the colorscale + * in color space, use `cmin` and `cmax`. Alternatively, `colorscale` may be + * a palette name string of the following list: Greys, YlGnBu, Greens, YlOrRd, + * Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, + * Earth, Electric, Viridis, Cividis. + */ + public var colorscale: Value? by value() // TODO() + + /** + * Determines whether the colorscale is a default palette (`true`) or + * the palette determined by `colorscale`. Has an effect only if + * in `color` is set to a numerical array. In case `colorscale` + * is unspecified or `autocolorscale` is true, the default palette + * will be chosen according to whether numbers in the `color` array + * are all positive, all negative or mixed. + * Default: true. + */ + public var autocolorscale: Boolean? by boolean() // TODO("colorscale first!") + + /** + * Reverses the color mapping if true. Has an effect only if + * in `color` is set to a numerical array. If true, `cmin` + * will correspond to the last color in the array and `cmax` + * will correspond to the first color. + */ + public var reversescale: Boolean? by boolean() // TODO("colorscale first!") + + /** + * Sets a reference to a shared color axis. References to these + * shared color axes are "coloraxis", "coloraxis2", "coloraxis3", etc. + * Settings for these shared color axes are set in the layout, + * under `coloraxis`, `coloraxis2`, etc. Note that multiple + * color scales can be linked to the same color axis. + */ + // var coloraxis TODO() + + /** + * Sets the border line color of the outlier sample points. Defaults to marker.color + */ + public val outliercolor: Color by color() + + /** + * Sets the border line width (in px) of the outlier sample points. + * Default: 1 + */ + public var outlierwidth: Number by numberGreaterThan(0) + + public fun colors(colors: Iterable) { + color.value = colors.map { Value.of(it) }.asValue() + } + + public companion object : SchemeSpec(::MarkerLine) +} + +public enum class TextPosition { + @JsName("topLeft") + `top left`, + + @JsName("topCenter") + `top center`, + + @JsName("topRight") + `top right`, + + @JsName("middleLeft") + `middle left`, + + @JsName("middleCenter") + `middle center`, + + @JsName("middleRight") + `middle right`, + + @JsName("bottomLeft") + `bottom left`, + + @JsName("bottomCenter") + `bottom center`, + + @JsName("bottomRight") + `bottom right`, + + // pie + inside, + outside, + auto, + none +} + +public class Font : Scheme() { + /** + * HTML font family - the typeface that will be applied + * by the web browser. The web browser will only be able + * to apply a font if it is available on the system + * which it operates. Provide multiple font families, + * separated by commas, to indicate the preference + * in which to apply fonts if they aren't available + * on the system. The Chart Studio Cloud (at https://chart-studio.plotly.com or on-premise) + * generates images on a server, where only a select number + * of fonts are installed and supported. These include "Arial", + * "Balto", "Courier New", "Droid Sans",, "Droid Serif", + * "Droid Sans Mono", "Gravitas One", "Old Standard TT", + * "Open Sans", "Overpass", "PT Sans Narrow", "Raleway", "Times New Roman". + */ + public var family: String? by string() + + /** + * HTML font family + */ + public var familiesList: List? by stringList(key = "family".asName()) + + public var size: Number by numberGreaterThan(1) + + public var sizesList: List by numberList(key = "size".asName()) + + public val color: Color by color() + + public fun colors(array: Iterable) { + color.value = array.map { Value.of(it) }.asValue() + } + + public companion object : SchemeSpec(::Font) +} + +public enum class Ref { + container, + paper +} + +public class Title : Scheme() { + /** + * Sets the plot's title. + */ + public var text: String? by string() + + /** + * Sets the title font. + */ + public var font: Font by scheme(Font) + + /** + * Sets the container `x` refers to. "container" spans the entire `width` of the plot. + * "paper" refers to the width of the plotting area only. Default: container. + */ + public var xref: Ref by enum(Ref.container) + + /** + * Sets the container `y` refers to. "container" spans the entire `height` of the plot. + * "paper" refers to the height of the plotting area only. Default: container. + */ + public var yref: Ref by enum(Ref.container) + + /** + * Sets the x position with respect to `xref` in normalized coordinates from "0" (left) to "1" (right). + * Default: 0.5 + */ + public var x: Number by numberInRange(0.0..1.0) + + /** + * Sets the y position with respect to `yref` in normalized coordinates from "0" (bottom) to "1" (top). + * "auto" places the baseline of the title onto the vertical center of the top margin. Default: auto. + */ + public var y: Number by numberInRange(0.0..1.0) + + /** + * Sets the title's horizontal alignment with respect to its x position. "left" means that the title starts at x, + * "right" means that the title ends at x and "center" means that the title's center is at x. + * "auto" divides `xref` by three and calculates the `xanchor` value automatically based on the value of `x`. + */ + public var xanchor: XAnchor by enum(XAnchor.auto) + + /** + * Sets the title's vertical alignment with respect to its y position. "top" means that the title's cap line is at y, + * "bottom" means that the title's baseline is at y and "middle" means that the title's midline is at y. + * "auto" divides `yref` by three and calculates the `yanchor` value automatically based on the value of `y`. + */ + public var yanchor: YAnchor by enum(YAnchor.auto) + + /** + * Sets the padding of the title. Each padding value only applies when the corresponding `xanchor`/`yanchor` + * value is set accordingly. E.g. for left padding to take effect, `xanchor` must be set to "left". + * The same rule applies if `xanchor`/`yanchor` is determined automatically. Padding is muted if + * the respective anchor value is "middle"/"center". + */ + public var pad: Margin by scheme(Margin) + + public fun font(block: Font.() -> Unit) { + font = Font(block) + } + + public fun pad(block: Margin.() -> Unit) { + pad = Margin(block) + } + + public companion object : SchemeSpec(::Title) +} + +public enum class ErrorType { + percent, + constant, + sqrt, + data +} + +public class Error : Scheme() { + /** + * Determines whether or not this set of error bars is visible. + */ + public var visible: Boolean? by boolean() + + /** + * Enumerated , one of ("percent" | "constant" | "sqrt" | "data") + * Determines the rule used to generate the error bars. + * If "constant`, the bar lengths are of a constant value. + * Set this constant in `value`. If "percent", the bar lengths correspond + * to a percentage of underlying data. Set this percentage in `value`. + * If "sqrt", the bar lengths correspond to the square of the underlying data. + * If "data", the bar lengths are set with data set `array`. + * Default: constant. + */ + public var type: ErrorType by enum(ErrorType.constant) + + /** + * Determines whether or not the error bars have the same length in both + * direction (top/bottom for vertical bars, left/right for horizontal bars. + */ + public var symmetric: Boolean? by boolean() + + /** + * Sets the data corresponding the length of each error bar. + * Values are plotted relative to the underlying data. + */ + public var array: List<Number> by numberList() + + /** + * Sets the data corresponding the length of each error bar + * in the bottom (left) direction for vertical (horizontal) bars. + * Values are plotted relative to the underlying data. + */ + public var arrayminus: List<Number> by numberList() + + /** + * Number greater than or equal to 0. + * Sets the value of either the percentage (if `type` is set to "percent") + * or the constant (if `type` is set to "constant") + * corresponding to the lengths of the error bars. + * Default: 10. + */ + public var value: Number by numberGreaterThan(0) + + /** + * Number greater than or equal to 0. + * Sets the value of either the percentage (if `type` is set to "percent") + * or the constant (if `type` is set to "constant") + * corresponding to the lengths of the error bars in the bottom (left) + * direction for vertical (horizontal) bars. + * Default: 10. + */ + public var valueminus: Number by numberGreaterThan(0) + + /** + * Sets the stoke color of the error bars. + */ + public val color: Color by color() + + /** + * Sets the thickness (in px) of the error bars. + * Default: 2. + */ + public var thickness: Number by numberGreaterThan(0) + + /** + * Sets the width (in px) of the cross-bar at both ends of the error bars. + */ + public var width: Number by numberGreaterThan(0) + + /** + * Integer greater than or equal to 0. + * Default: 0. + */ + public var traceref: Int by intGreaterThan(0) + + /** + * Integer greater than or equal to 0. + * Default: 0. + */ + public var tracerefminus: Int by intGreaterThan(0) + + public companion object : SchemeSpec<Error>(::Error) +} + +public enum class MeasureMode { + fraction, + pixels +} + +public enum class ConstrainText { + inside, + outside, + both, + none +} + +public class ColorBar : Scheme() { + /** + * Determines whether this color bar's thickness (i.e. the measure + * in the constant color direction) is set in units of plot "fraction" + * or in "pixels" (default). Use `thickness` to set the value. + */ + public var thicknessmode: MeasureMode by enum(MeasureMode.pixels) + + /** + * Sets the thickness of the color bar. + * This measure excludes the size of the padding, ticks and labels. + * Default: 30. + */ + public var thickness: Number by numberGreaterThan(0) + + /** + * Determines whether this color bar's length (i.e. the measure + * in the color variation direction) is set in units of plot + * "fraction" (default) or in "pixels. Use `len` to set the value. + */ + public var lenmode: MeasureMode by enum(MeasureMode.fraction) + + /** + * Sets the length of the color bar This measure excludes + * the padding of both ends. That is, the color bar length + * is this length minus the padding on both ends. + * Default: 1. + */ + public var len: Number by numberGreaterThan(0) + + /** + * Sets the x position of the color bar (in plot fraction). + * Default: 1.02. + */ + public var x: Number by numberInRange(-2.0..3.0) + + /** + * Sets this color bar's horizontal position anchor. + * This anchor binds the `x` position to the "left" (default), + * "center" or "right" of the color bar. + */ + public var xanchor: XAnchor by enum(XAnchor.left) + + /** + * Sets the amount of padding (in px) along the x direction. + * Default: 10. + */ + public var xpad: Number by numberGreaterThan(0) + + /** + * Sets the y position of the color bar (in plot fraction). + * Default: 0.5. + */ + public var y: Number by numberInRange(-2.0..3.0) + + /** + * Sets this color bar's vertical position anchor. + * This anchor binds the `y` position to the "top", + * "middle" (default) or "bottom" of the color bar. + */ + public var yanchor: YAnchor by enum(YAnchor.middle) + + /** + * Sets the amount of padding (in px) along the y direction. + * Default: 10. + */ + public var ypad: Int by intGreaterThan(0) + + /** + * Sets the axis line color. + * Default: #444. + */ + public val bordercolor: Color by color() + + /** + * Sets the width (in px) or the border enclosing this color bar. + * Default: 0. + */ + public var borderwidth: Number by numberGreaterThan(0) + + /** + * Sets the color of padded area. + * Default: rgba(0, 0, 0, 0). + */ + public val bgcolor: Color by color() + + public var title: Title by scheme(Title) + + /** + * Sets the width (in px) of the axis line. + * Default: 1. + */ + public var outlinewidth: Number by numberGreaterThan(0) + + /** + * Sets the axis line color. + * Default: #444. + */ + public val outlinecolor: Color by color() + + /** + * Constrain the size of text inside or outside a bar to be no larger than the bar itself. + */ + public var constraintext: ConstrainText by enum(ConstrainText.both) + + /** + * Sets the color bar's tick label font + */ + public var tickfont: Font by scheme(Font) + + public fun title(block: Title.() -> Unit) { + title = Title(block) + } + + public fun tickfont(block: Font.() -> Unit) { + tickfont = Font(block) + } + + public companion object : SchemeSpec<ColorBar>(::ColorBar) +} + +public enum class Orientation { + v, + h +} + +public enum class ContoursType { + levels, + constraint +} + +public enum class ContoursColoring { + fill, + heatmap, + lines, + none +} + +public enum class Calendar { + gregorian, + chinese, + coptic, + discworld, + ethiopian, + hebrew, + islamic, + julian, + mayan, + nanakshahi, + nepali, + persian, + jalali, + taiwan, + thai, + ummalqura +} + +public class Domain : Scheme() { + /** + * Sets the horizontal domain of this pie trace (in plot fraction). + * Default: [0, 1] + */ + public var x: List<Number> by numberList() + + /** + * Sets the vertical domain of this pie trace (in plot fraction). + * Default: [0, 1] + */ + public var y: List<Number> by numberList() + + /** + * If there is a layout grid, use the domain for this row in the grid for this pie trace. + */ + public var row: Int by intGreaterThan(0) + + /** + * If there is a layout grid, use the domain for this column in the grid for this pie trace. + */ + public var column: Int by intGreaterThan(0) + + public companion object : SchemeSpec<Domain>(::Domain) +} + +public class Hoverlabel : Scheme() { + + /** + * Sets the background color of the hover labels for this trace. + * */ + public var bgcolor: Color = Color(this, "bgcolor".asName()) + + /** + * Sets the border color of the hover labels for this trace. + * */ + public var bordercolor: Color = Color(this, "bordercolor".asName()) + + /** + * Sets the font used in hover labels. + * */ + public var font: Font by scheme(Font) + + /** + * Sets the horizontal alignment of the text content within hover label box. Has an effect + * only if the hover label text spans more two or more lines. + * + * Defaults to `'auto'`. + * */ + public var align: TraceValues = TraceValues(this, "align".asName()) + + /** + * Sets the default length (in number of characters) of the trace name in the hover labels for all traces. + * -1 shows the whole name regardless of length. 0-3 shows the first 0-3 characters, and an integer >3 will + * show the whole name if it is less than that many characters, but if it is longer, will truncate to + * `namelength - 3` characters and add an ellipsis. + * */ + public var namelength: Number by numberGreaterThan(-1) + + /** + * Complementary property to [namelength] to allow passing a list of lengths. + * */ + public var namelengths: List<Number> by numberList(-1, key = "namelength".asName()) + + public fun bgcolors(array: Iterable<Any>) { + bgcolor.value = array.map { Value.of(it) }.asValue() + } + + public fun bordercolors(array: Iterable<Any>) { + bordercolor.value = array.map { Value.of(it) }.asValue() + } + + public fun font(block: Font.() -> Unit) { + font = Font(block) + } + + public fun align(align: HorizontalAlign) { + align(listOf(align)) + } + + public fun align(alignments: List<HorizontalAlign>) { + this.align.set(alignments) + } + + public fun align(vararg alignments: HorizontalAlign) { + this.align.set(alignments.toList()) + } + + public companion object : SchemeSpec<Hoverlabel>(::Hoverlabel) +} + +/** + * A base class for Plotly traces + */ +public open class Trace : Scheme() { + public fun axis(axisName: String): TraceValues = TraceValues(this, Name.parse(axisName)) + + public val axis: ReadOnlyProperty<Scheme, TraceValues> = ReadOnlyProperty { thisRef, property -> + TraceValues(thisRef, property.name.asName()) + } + + /** + * Sets the x coordinates. + */ + public val x: TraceValues = axis(X_AXIS) + + /** + * Alternate to `x`. Builds a linear space of x coordinates. + * Use with `dx` where `x0` is the starting coordinate and `dx` the step. + * Default: 0. + */ + public var x0: Value? by value() + + /** + * Sets the x coordinate step. See `x0` for more info. + * Default: 1. + */ + public var dx: Number by numberGreaterThan(0) + + /** + * Sets the y coordinates. + */ + public val y: TraceValues = axis(Y_AXIS) + + /** + * Z coordinates + */ + public val z: TraceValues = axis(Z_AXIS) + + /** + * Alternate to `y`. Builds a linear space of y coordinates. + * Use with `dy` where `y0` is the starting coordinate and `dy` the step. + */ + public var y0: Value? by value() + + /** + * Sets the y coordinate step. See `y0` for more info. + * Default: 1. + */ + public var dy: Number by numberGreaterThan(0) + + /** + * Determines whether or not markers and text nodes are clipped about the subplot axes. + * To show markers and text nodes above axis lines and tick labels, make sure + * to set `xaxis.layer` and `yaxis.layer` to "below traces". + */ + public var cliponaxis: Boolean? by boolean() + + /** + * Determines whether or not the color domain is computed with respect to + * the input data (here in `z`) or the bounds set in `zmin` and `zmax` + * Defaults to `false` when `zmin` and `zmax` are set by the user. + * + */ + public var zauto: Boolean? by boolean() + + /** + * Sets the lower bound of the color domain. Value should have the same units + * as in `z` and if set, `zmax` must be set as well. + */ + public var zmin: Number? by number() + + /** + * Sets the upper bound of the color domain. Value should have the same units + * as in `z` and if set, `zmin` must be set as well. + */ + public var zmax: Number? by number() + + /** + * Sets the mid-point of the color domain by scaling `zmin` and/or `zmax` + * to be equidistant to this point. Value should have the same units as in `z`. + * Has no effect when `zauto` is `false`. + */ + public var zmid: Number? by number() + + /** + * Data array. Sets the values of the sectors. + * If omitted, we count occurrences of each label. + */ + public var values: List<Value> by listOfValues() + + /** + * Data array. Sets the sector labels. If `labels` entries + * are duplicated, we sum associated `values` or simply + * count occurrences if `values` is not provided. + * For other array attributes (including color) we use the first + * non-empty entry among all occurrences of the label. + */ + public var labels: List<Value> by listOfValues() + + public var line: LayoutLine by scheme(LayoutLine) + + /** + * Sets the colorscale. The colorscale must be an array + * containing arrays mapping a normalized value to an rgb, + * rgba, hex, hsl, hsv, or named color string. + */ + public var colorscale: Value? by value() + + public var colorbar: ColorBar by scheme(ColorBar) + + /** + * Sets the fill color if `contours.type` is "constraint". Defaults to + * a half-transparent variant of the line color, marker color, or marker line color, whichever is available. + */ + public val fillcolor: Color by color() + + /** + * Sets the trace name. The trace name appear as the legend item and on hover. + */ + public var name: String? by string() + + public var type: TraceType by enum(TraceType.scatter) + + /** + * Enumerated , one of ( true | false | "legendonly" ) + * Determines whether or not this trace is visible. + * If "legendonly", the trace is not drawn, but can appear + * as a legend item (provided that the legend itself is visible). + * Default: true. + */ + public var visible: Visible by enum(Visible.`true`) + + /** + * Determines whether or not an item corresponding to this trace is shown in the legend. + * Default: true + */ + public var showlegend: Boolean? by boolean() + + /** + * Sets the legend group for this trace. Traces part of + * the same legend group hide/show at the same time when toggling legend items. + * Default: "" + */ + public var legendgroup: String? by string() + + /** + * Sets the opacity of the trace. + * Default: 1. + */ + public var opacity: Number by numberInRange(0.0..1.0) + + //var line by scheme(Line) + + public var marker: Marker by scheme(Marker) + + /** + * Sets hover text elements associated with each (x,y) pair. If a single string, the same string appears over all + * the data points. If an array of string, the items are mapped in order to the this trace's (x,y) coordinates. + * To be seen, trace `hoverinfo` must contain a "text" flag. + */ + public val hovertext: TraceValues by axis + + /** + * Sets text elements associated with each (x,y) pair. + * The same string appears over all the data points. + * If trace `hoverinfo` contains a "text" flag and "hovertext" is not set, + * these elements will be seen in the hover labels. + */ + public val text: TraceValues = axis(TEXT_AXIS) + + /** + * Sets the position of the `text` elements + * with respects to the (x,y) coordinates. + * Default: "middle center". + */ + public var textposition: TextPosition by enum(TextPosition.`middle center`) + + /** + * Sets the positions of the `text` elements + * with respects to the (x,y) coordinates. + * Default: "middle center". + */ + @UnstablePlotlyAPI + public var textpositionsList: List<Value> by listOfValues(key = "textposition".asName()) + + /** + * Sets the text font. + */ + public var textfont: Font by scheme(Font) + + /** + * Flaglist string. Any combination of "x", "y", "z", "text", "name" joined with a "+" OR "all" or "none" or "skip". + * Examples: "x", "y", "x+y", "x+y+z", "all", default: "all". Determines which trace information appear on hover. + * If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, + * click and hover events are still fired. + */ + public var hoverinfo: String? by string() + + public var error_x: Error by scheme(Error) + + public var error_y: Error by scheme(Error) + + /** + * Sets the orientation of the plot(s). + * If "vertical" ("horizontal"), the data + * is visualized along the vertical (horizontal). + */ + public var orientation: Orientation by enum(Orientation.h) + + /** + * If there are multiple violins that should be sized according to + * some metric (see `scalemode`), link them by providing a non-empty + * group id here shared by every trace in the same group. + * If a violin's `width` is undefined, `scalegroup` will default + * to the trace's name. In this case, violins with the same names + * will be linked together. Default: "" + */ + public var scalegroup: String? by string() + + /** + * Determines whether or not a colorbar is displayed for this trace. + */ + public var showscale: Boolean? by boolean() + + /** + * Reverses the color mapping if true. If true, `zmin` will + * correspond to the last color in the array and `zmax` will correspond to the first color. + */ + public var reversescale: Boolean? by boolean() + + /** + * Transposes the z data. + */ + public var transpose: Boolean? by boolean() + + /** + * Determines whether or not gaps (i.e. {nan} or missing values) in the `z` data are filled in. + * It is defaulted to true if `z` is a one dimensional array and `zsmooth` is not false; + * otherwise it is defaulted to false. + */ + public var connectgaps: Boolean? by boolean() + + /** + * Sets the calendar system to use with `x` date data. + */ + public var xcalendar: Calendar by enum(Calendar.gregorian) + + /** + * Sets the calendar system to use with `y` date data. + */ + public var ycalendar: Calendar by enum(Calendar.gregorian) + + public var domain: Domain by scheme(Domain) + + public var hoverlabel: Hoverlabel by scheme(Hoverlabel) + + public fun values(array: Iterable<Any>) { + values = array.map { Value.of(it) } + } + + public fun labels(array: Iterable<Any>) { + labels = array.map { Value.of(it) } + } + + public fun colorbar(block: ColorBar.() -> Unit) { + colorbar = ColorBar(block) + } + + public fun textfont(block: Font.() -> Unit) { + textfont = Font(block) + } + + public fun marker(block: Marker.() -> Unit) { + marker = Marker(block) + } + + public fun line(block: LayoutLine.() -> Unit) { + line = LayoutLine(block) + } + + public fun error_x(block: Error.() -> Unit) { + error_x = Error(block) + } + + public fun error_y(block: Error.() -> Unit) { + error_y = Error(block) + } + + public fun domain(block: Domain.() -> Unit) { + domain = Domain(block) + } + + public fun hoverlabel(block: Hoverlabel.() -> Unit) { + hoverlabel = Hoverlabel(block) + } + + public companion object : SchemeSpec<Trace>(::Trace) { + public const val X_AXIS: String = "x" + public const val Y_AXIS: String = "y" + public const val Z_AXIS: String = "z" + public const val TEXT_AXIS: String = "text" + } +} + +public operator fun <T : Trace> SchemeSpec<T>.invoke( + xs: Any, + ys: Any? = null, + zs: Any? = null, + block: Trace.() -> Unit, +): T = invoke { + x.set(xs) + if (ys != null) y.set(ys) + if (zs != null) z.set(zs) + block() +} diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/TraceValues.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/TraceValues.kt new file mode 100644 index 00000000..156b3665 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/TraceValues.kt @@ -0,0 +1,57 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.Name + +/** + * Type-safe accessor class for values in the trace + */ +public class TraceValues internal constructor(public val owner: Scheme, name: Name) { + public var value: Value? by owner.value(key = name) + + public var doubles: DoubleArray + get() = value?.doubleArray?.copyOf() ?: doubleArrayOf() + set(value) { + this.value = DoubleArrayValue(value) + } + + public var numbers: Iterable<Number> + get() = value?.list?.map { it.numberOrNull ?: Double.NaN } ?: emptyList() + set(value) { + this.value = ListValue(value.map { it.asValue() }) + } + + public var strings: Iterable<String> + get() = value?.list?.map { it.string } ?: emptyList() + set(value) { + this.value = value.map { it.asValue() }.asValue() + } + + /** + * Smart fill for trace values. The following types are accepted: [DoubleArray], [IntArray], [Array] of primitive or string, + * [Iterable] of primitive or string. + */ + public fun set(values: Any?) { + value = when (values) { + null -> null + is DoubleArray -> values.asValue() + is IntArray -> values.map { it.asValue() }.asValue() + is Array<*> -> values.map { Value.of(it) }.asValue() + is Iterable<*> -> values.map { Value.of(it) }.asValue() + else -> error("Unrecognized values type ${values::class}") + } + } + + public operator fun invoke(vararg numbers: Number) { + this.numbers = numbers.asList() + } + + public operator fun invoke(vararg strings: String) { + this.strings = strings.asList() + } + + public operator fun invoke(lists: List<List<Number>>) { + this.value = lists.map { row -> row.map { it.asValue() }.asValue() }.asValue() + } + +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Violin.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Violin.kt new file mode 100644 index 00000000..cd36e293 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/Violin.kt @@ -0,0 +1,178 @@ +package space.kscience.plotly.models + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.listOfValues +import space.kscience.plotly.numberGreaterThan +import space.kscience.plotly.numberInRange +import kotlin.js.JsName + +public enum class ViolinScaleMode { + count, + width +} + +public enum class ViolinPoints { + all, + outliers, + suspectedoutliers, + `false` +} + +public enum class ViolinSide { + positive, + negative, + both +} + +public enum class ViolinHoveron { + violins, + points, + kde, + + @JsName("violinsAndPoints") + `violins+points`, + + @JsName("violinsAndKde") + `violins+kde`, + + @JsName("pointsAndKde") + `points+kde`, + + @JsName("violinsAndPointsAndKde") + `violins+points+kde`, + all +} + +public class MeanLine : Scheme() { + /** + * Sets the mean line width. + */ + public var width: Number by numberGreaterThan(0) + + /** + * Sets the mean line color. + */ + public val color: Color by color() + + /** + * Determines if a line corresponding to the sample's + * mean is shown inside the violins. If `box.visible` is + * turned on, the mean line is drawn inside the inner box. + * Otherwise, the mean line is drawn from one side of the violin to other. + */ + public var visible: Boolean? by boolean() + + public companion object : SchemeSpec<MeanLine>(::MeanLine) +} + +public enum class SpanMode { + soft, + hard, + manual +} + +public class ViolinBox : Scheme() { + /** + * Sets the width of the inner box plots relative to the violins' width. + * For example, with 1, the inner box plots are as wide as the violins. + * Default: 0.25. + */ + public var width: Number by numberInRange(0.0..1.0) + + /** + * Determines if an miniature box plot is drawn inside the violins. + */ + public var visible: Boolean? by boolean() + + /** + * Sets the inner box plot fill color. + */ + public val fillcolor: Color by color() + + public companion object : SchemeSpec<ViolinBox>(::ViolinBox) +} + +public class Violin : Trace() { + init { + type = TraceType.violin + } + + /** + * Sets the metric by which the width of each violin is determined. + * "width" (default) means each violin has the same (max) width + * "count" means the violins are scaled by the number + * of sample points making up each violin. + */ + public var scalemode: ViolinScaleMode by enum(ViolinScaleMode.width) + + /** + * Determines on which side of the position value the density + * function making up one half of a violin is plotted. + * Useful when comparing two violin traces under "overlay" mode, + * where one trace has `side` set to "positive" and the other to "negative". + */ + public var side: ViolinSide by enum(ViolinSide.both) + + /** + * Do the hover effects highlight individual violins or sample + * points or the kernel density estimate or any combination of them? + */ + public var hoveron: ViolinHoveron by enum(ViolinHoveron.`violins+points+kde`) + + public var meanline: MeanLine by scheme(MeanLine) + + /** + * If "outliers", only the sample points lying outside the whiskers + * are shown If "suspectedoutliers", the outlier points are shown + * and points either less than 4"Q1-3"Q3 or greater than 4"Q3-3"Q1 + * are highlighted (see `outliercolor`) If "all", all sample points + * are shown If "false", only the violins are shown with no sample points. + */ + public var points: ViolinPoints by enum(ViolinPoints.`false`) + + /** + * Sets the method by which the span in data space where the density function will be computed. + * "soft" means the span goes from the sample's minimum value minus two bandwidths to the sample's + * maximum value plus two bandwidths. "hard" means the span goes from the sample's minimum to its maximum value. + * For custom span settings, use mode "manual" and fill in the `span` attribute. + */ + public var spanmode: SpanMode by enum(SpanMode.soft) + + /** + * Sets the span in data space for which the density function will be computed. + * Has an effect only when `spanmode` is set to "manual". + */ + public var span: List<Value> by listOfValues() + + public var box: ViolinBox by scheme(ViolinBox) + + /** + * Sets the amount of jitter in the sample points drawn. + * If "0", the sample points align along the distribution axis. + * If "1", the sample points are drawn in a random jitter + * of width equal to the width of the violins. + */ + public var jitter: Number by numberInRange(0.0..1.0) + + /** + * Sets the position of the sample points in relation to the violins. + * If "0", the sample points are places over the center of the violins. + * Positive (negative) values correspond to positions to the right (left) + * for vertical violins and above (below) for horizontal violins. + */ + public var pointpos: Number by numberInRange(-2.0..2.0) + + public fun meanline(block: MeanLine.() -> Unit) { + meanline = MeanLine(block) + } + + public fun box(block: ViolinBox.() -> Unit) { + box = ViolinBox(block) + } + + public fun span(array: Iterable<Any>) { + span = array.map { Value.of(it) } + } + + public companion object : SchemeSpec<Violin>(::Violin) +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/fillTrace.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/fillTrace.kt new file mode 100644 index 00000000..e18bcff8 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/models/fillTrace.kt @@ -0,0 +1,63 @@ +package space.kscience.plotly.models + +import space.kscience.plotly.UnstablePlotlyAPI + +// Utilities to fill traces with values + +/** + * Append x and y axis values to a trace with optional x error [xErr] and y error [yErr] + */ +@UnstablePlotlyAPI +public fun Trace.appendXY(x: Number, y: Number, xErr: Number? = null, yErr: Number? = null) { + this.x.numbers += x + this.y.numbers += y + xErr?.let { error_x.array += xErr } + yErr?.let { error_y.array += yErr } +} + +/** + * Append trace values using given [pairs] of x-y number coordinates + */ +@UnstablePlotlyAPI +public fun Trace.appendXY(vararg pairs: Pair<Number, Number>) { + this.x.numbers += pairs.map { it.first } + this.y.numbers += pairs.map { it.second } +} + +/** + * Fill trace [x] and [y] with values based on a given integer [xRange] and a numeric [function]. Old values are erased. + */ +@UnstablePlotlyAPI +public fun Trace.functionXY(xRange: IntRange, function: (Int) -> Number) { + x.numbers = xRange + y.numbers = xRange.map(function) +} + +/** + * Fill trace [x] and [y] with values based on given [xs] and a [function] for y values. Old values are erased. + */ +@UnstablePlotlyAPI +public fun Trace.functionXY(xs: Iterable<Number>, function: (Double) -> Number) { + x.numbers = xs + y.numbers = xs.map { function(it.toDouble()) } +} + +/** + * Fill values in [xRange] with given [step] using given [function]. Old values are erased. + */ +@UnstablePlotlyAPI +public fun Trace.functionXY( + xRange: ClosedFloatingPointRange<Double>, + step: Double = 1.0, + function: (Double) -> Number, +) { + val xs = buildList { + var value = xRange.start + while (value <= xRange.endInclusive) { + add(value) + value += step + } + } + x.numbers = xs + y.numbers = xs.map { function(it) } +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/palettes/T10.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/palettes/T10.kt new file mode 100644 index 00000000..06d14837 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/palettes/T10.kt @@ -0,0 +1,18 @@ +package space.kscience.plotly.palettes + +/** + * Tableau Colors - the 'T10' categorical palette (the default color cycle) + */ + +public object T10 { + public const val BLUE: String = "#1f77b4" + public const val ORANGE: String = "#ff7f0e" + public const val GREEN: String = "#2ca02c" + public const val RED: String = "#d62728" + public const val PURPLE: String = "#9467bd" + public const val BROWN: String = "#8c564b" + public const val PINK: String = "#e377c2" + public const val GRAY: String = "#7f7f7f" + public const val OLIVE: String = "#bcbd22" + public const val CYAN: String = "#17becf" +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/palettes/Xkcd.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/palettes/Xkcd.kt new file mode 100644 index 00000000..78770325 --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/palettes/Xkcd.kt @@ -0,0 +1,945 @@ +package space.kscience.plotly.palettes + +/** + * Color names from xkcd color survey + */ + +@Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING", "unused") +public object Xkcd { + const val CLOUDY_BLUE = "#ACC2D9" + const val DARK_PASTEL_GREEN = "#56AE57" + const val DUST = "#B2996E" + const val ELECTRIC_LIME = "#A8FF04" + const val FRESH_GREEN = "#69D84F" + const val LIGHT_EGGPLANT = "#894585" + const val NASTY_GREEN = "#70B23F" + const val REALLY_LIGHT_BLUE = "#D4FFFF" + const val TEA = "#65AB7C" + const val WARM_PURPLE = "#952E8F" + const val YELLOWISH_TAN = "#FCFC81" + const val CEMENT = "#A5A391" + const val DARK_GRASS_GREEN = "#388004" + const val DUSTY_TEAL = "#4C9085" + const val GREY_TEAL = "#5E9B8A" + const val MACARONI_AND_CHEESE = "#EFB435" + const val PINKISH_TAN = "#D99B82" + const val SPRUCE = "#0A5F38" + const val STRONG_BLUE = "#0C06F7" + const val TOXIC_GREEN = "#61DE2A" + const val WINDOWS_BLUE = "#3778BF" + const val BLUE_BLUE = "#2242C7" + const val BLUE_WITH_A_HINT_OF_PURPLE = "#533CC6" + const val BOOGER = "#9BB53C" + const val BRIGHT_SEA_GREEN = "#05FFA6" + const val DARK_GREEN_BLUE = "#1F6357" + const val DEEP_TURQUOISE = "#017374" + const val GREEN_TEAL = "#0CB577" + const val STRONG_PINK = "#FF0789" + const val BLAND = "#AFA88B" + const val DEEP_AQUA = "#08787F" + const val LAVENDER_PINK = "#DD85D7" + const val LIGHT_MOSS_GREEN = "#A6C875" + const val LIGHT_SEAFOAM_GREEN = "#A7FFB5" + const val OLIVE_YELLOW = "#C2B709" + const val PIG_PINK = "#E78EA5" + const val DEEP_LILAC = "#966EBD" + const val DESERT = "#CCAD60" + const val DUSTY_LAVENDER = "#AC86A8" + const val PURPLEY_GREY = "#947E94" + const val PURPLY = "#983FB2" + const val CANDY_PINK = "#FF63E9" + const val LIGHT_PASTEL_GREEN = "#B2FBA5" + const val BORING_GREEN = "#63B365" + const val KIWI_GREEN = "#8EE53F" + const val LIGHT_GREY_GREEN = "#B7E1A1" + const val ORANGE_PINK = "#FF6F52" + const val TEA_GREEN = "#BDF8A3" + const val VERY_LIGHT_BROWN = "#D3B683" + const val EGG_SHELL = "#FFFCC4" + const val EGGPLANT_PURPLE = "#430541" + const val POWDER_PINK = "#FFB2D0" + const val REDDISH_GREY = "#997570" + const val BABY_SHIT_BROWN = "#AD900D" + const val LILIAC = "#C48EFD" + const val STORMY_BLUE = "#507B9C" + const val UGLY_BROWN = "#7D7103" + const val CUSTARD = "#FFFD78" + const val DARKISH_PINK = "#DA467D" + const val DEEP_BROWN = "#410200" + const val GREENISH_BEIGE = "#C9D179" + const val MANILLA = "#FFFA86" + const val OFF_BLUE = "#5684AE" + const val BATTLESHIP_GREY = "#6B7C85" + const val BROWNY_GREEN = "#6F6C0A" + const val BRUISE = "#7E4071" + const val KELLEY_GREEN = "#009337" + const val SICKLY_YELLOW = "#D0E429" + const val SUNNY_YELLOW = "#FFF917" + const val AZUL = "#1D5DEC" + const val DARKGREEN = "#054907" + const val LICHEN = "#8FB67B" + const val LIGHT_LIGHT_GREEN = "#C8FFB0" + const val PALE_GOLD = "#FDDE6C" + const val SUN_YELLOW = "#FFDF22" + const val TAN_GREEN = "#A9BE70" + const val BURPLE = "#6832E3" + const val BUTTERSCOTCH = "#FDB147" + const val TOUPE = "#C7AC7D" + const val DARK_CREAM = "#FFF39A" + const val INDIAN_RED = "#850E04" + const val LIGHT_LAVENDAR = "#EFC0FE" + const val POISON_GREEN = "#40FD14" + const val BABY_PUKE_GREEN = "#B6C406" + const val BRIGHT_YELLOW_GREEN = "#9DFF00" + const val CHARCOAL_GREY = "#3C4142" + const val SQUASH = "#F2AB15" + const val CINNAMON = "#AC4F06" + const val LIGHT_PEA_GREEN = "#C4FE82" + const val RADIOACTIVE_GREEN = "#2CFA1F" + const val RAW_SIENNA = "#9A6200" + const val BABY_PURPLE = "#CA9BF7" + const val COCOA = "#875F42" + const val LIGHT_ROYAL_BLUE = "#3A2EFE" + const val ORANGEISH = "#FD8D49" + const val RUST_BROWN = "#8B3103" + const val SAND_BROWN = "#CBA560" + const val SWAMP = "#698339" + const val TEALISH_GREEN = "#0CDC73" + const val BURNT_SIENA = "#B75203" + const val CAMO = "#7F8F4E" + const val DUSK_BLUE = "#26538D" + const val FERN = "#63A950" + const val OLD_ROSE = "#C87F89" + const val PALE_LIGHT_GREEN = "#B1FC99" + const val PEACHY_PINK = "#FF9A8A" + const val ROSY_PINK = "#F6688E" + const val LIGHT_BLUISH_GREEN = "#76FDA8" + const val LIGHT_BRIGHT_GREEN = "#53FE5C" + const val LIGHT_NEON_GREEN = "#4EFD54" + const val LIGHT_SEAFOAM = "#A0FEBF" + const val TIFFANY_BLUE = "#7BF2DA" + const val WASHED_OUT_GREEN = "#BCF5A6" + const val BROWNY_ORANGE = "#CA6B02" + const val NICE_BLUE = "#107AB0" + const val SAPPHIRE = "#2138AB" + const val GREYISH_TEAL = "#719F91" + const val ORANGEY_YELLOW = "#FDB915" + const val PARCHMENT = "#FEFCAF" + const val STRAW = "#FCF679" + const val VERY_DARK_BROWN = "#1D0200" + const val TERRACOTA = "#CB6843" + const val UGLY_BLUE = "#31668A" + const val CLEAR_BLUE = "#247AFD" + const val CREME = "#FFFFB6" + const val FOAM_GREEN = "#90FDA9" + const val LIGHT_GOLD = "#FDDC5C" + const val SEAFOAM_BLUE = "#78D1B6" + const val TOPAZ = "#13BBAF" + const val VIOLET_PINK = "#FB5FFC" + const val WINTERGREEN = "#20F986" + const val YELLOW_TAN = "#FFE36E" + const val DARK_FUCHSIA = "#9D0759" + const val INDIGO_BLUE = "#3A18B1" + const val LIGHT_YELLOWISH_GREEN = "#C2FF89" + const val PALE_MAGENTA = "#D767AD" + const val RICH_PURPLE = "#720058" + const val SUNFLOWER_YELLOW = "#FFDA03" + const val LEATHER = "#AC7434" + const val RACING_GREEN = "#014600" + const val VIVID_PURPLE = "#9900FA" + const val DARK_ROYAL_BLUE = "#02066F" + const val HAZEL = "#8E7618" + const val MUTED_PINK = "#D1768F" + const val BOOGER_GREEN = "#96B403" + const val CANARY = "#FDFF63" + const val COOL_GREY = "#95A3A6" + const val DARK_TAUPE = "#7F684E" + const val DARKISH_PURPLE = "#751973" + const val TRUE_GREEN = "#089404" + const val CORAL_PINK = "#FF6163" + const val DARK_SAGE = "#598556" + const val DARK_SLATE_BLUE = "#214761" + const val FLAT_BLUE = "#3C73A8" + const val MUSHROOM = "#BA9E88" + const val RICH_BLUE = "#021BF9" + const val DIRTY_PURPLE = "#734A65" + const val GREENBLUE = "#23C48B" + const val ICKY_GREEN = "#8FAE22" + const val LIGHT_KHAKI = "#E6F2A2" + const val WARM_BLUE = "#4B57DB" + const val DARK_HOT_PINK = "#D90166" + const val DEEP_SEA_BLUE = "#015482" + const val CARMINE = "#9D0216" + const val DARK_YELLOW_GREEN = "#728F02" + const val PALE_PEACH = "#FFE5AD" + const val PLUM_PURPLE = "#4E0550" + const val GOLDEN_ROD = "#F9BC08" + const val NEON_RED = "#FF073A" + const val OLD_PINK = "#C77986" + const val VERY_PALE_BLUE = "#D6FFFE" + const val BLOOD_ORANGE = "#FE4B03" + const val GRAPEFRUIT = "#FD5956" + const val SAND_YELLOW = "#FCE166" + const val CLAY_BROWN = "#B2713D" + const val DARK_BLUE_GREY = "#1F3B4D" + const val FLAT_GREEN = "#699D4C" + const val LIGHT_GREEN_BLUE = "#56FCA2" + const val WARM_PINK = "#FB5581" + const val DODGER_BLUE = "#3E82FC" + const val GROSS_GREEN = "#A0BF16" + const val ICE = "#D6FFFA" + const val METALLIC_BLUE = "#4F738E" + const val PALE_SALMON = "#FFB19A" + const val SAP_GREEN = "#5C8B15" + const val ALGAE = "#54AC68" + const val BLUEY_GREY = "#89A0B0" + const val GREENY_GREY = "#7EA07A" + const val HIGHLIGHTER_GREEN = "#1BFC06" + const val LIGHT_LIGHT_BLUE = "#CAFFFB" + const val LIGHT_MINT = "#B6FFBB" + const val RAW_UMBER = "#A75E09" + const val VIVID_BLUE = "#152EFF" + const val DEEP_LAVENDER = "#8D5EB7" + const val DULL_TEAL = "#5F9E8F" + const val LIGHT_GREENISH_BLUE = "#63F7B4" + const val MUD_GREEN = "#606602" + const val PINKY = "#FC86AA" + const val RED_WINE = "#8C0034" + const val SHIT_GREEN = "#758000" + const val TAN_BROWN = "#AB7E4C" + const val DARKBLUE = "#030764" + const val ROSA = "#FE86A4" + const val LIPSTICK = "#D5174E" + const val PALE_MAUVE = "#FED0FC" + const val CLARET = "#680018" + const val DANDELION = "#FEDF08" + const val ORANGERED = "#FE420F" + const val POOP_GREEN = "#6F7C00" + const val RUBY = "#CA0147" + const val DARK = "#1B2431" + const val GREENISH_TURQUOISE = "#00FBB0" + const val PASTEL_RED = "#DB5856" + const val PISS_YELLOW = "#DDD618" + const val BRIGHT_CYAN = "#41FDFE" + const val DARK_CORAL = "#CF524E" + const val ALGAE_GREEN = "#21C36F" + const val DARKISH_RED = "#A90308" + const val REDDY_BROWN = "#6E1005" + const val BLUSH_PINK = "#FE828C" + const val CAMOUFLAGE_GREEN = "#4B6113" + const val LAWN_GREEN = "#4DA409" + const val PUTTY = "#BEAE8A" + const val VIBRANT_BLUE = "#0339F8" + const val DARK_SAND = "#A88F59" + const val SAFFRON = "#FEB209" + const val TWILIGHT = "#4E518B" + const val WARM_BROWN = "#964E02" + const val BLUEGREY = "#85A3B2" + const val BUBBLE_GUM_PINK = "#FF69AF" + const val DUCK_EGG_BLUE = "#C3FBF4" + const val GREENISH_CYAN = "#2AFEB7" + const val PETROL = "#005F6A" + const val ROYAL = "#0C1793" + const val BUTTER = "#FFFF81" + const val DUSTY_ORANGE = "#F0833A" + const val OFF_YELLOW = "#F1F33F" + const val PALE_OLIVE_GREEN = "#B1D27B" + const val ORANGISH = "#FC824A" + const val LEAF = "#71AA34" + const val LIGHT_BLUE_GREY = "#B7C9E2" + const val DRIED_BLOOD = "#4B0101" + const val LIGHTISH_PURPLE = "#A552E6" + const val RUSTY_RED = "#AF2F0D" + const val LAVENDER_BLUE = "#8B88F8" + const val LIGHT_GRASS_GREEN = "#9AF764" + const val LIGHT_MINT_GREEN = "#A6FBB2" + const val SUNFLOWER = "#FFC512" + const val VELVET = "#750851" + const val BRICK_ORANGE = "#C14A09" + const val LIGHTISH_RED = "#FE2F4A" + const val PURE_BLUE = "#0203E2" + const val TWILIGHT_BLUE = "#0A437A" + const val VIOLET_RED = "#A50055" + const val YELLOWY_BROWN = "#AE8B0C" + const val CARNATION = "#FD798F" + const val MUDDY_YELLOW = "#BFAC05" + const val DARK_SEAFOAM_GREEN = "#3EAF76" + const val DEEP_ROSE = "#C74767" + const val DUSTY_RED = "#B9484E" + const val LEMON_LIME = "#BFFE28" + const val BROWN_YELLOW = "#B29705" + const val PURPLE_BROWN = "#673A3F" + const val WISTERIA = "#A87DC2" + const val BANANA_YELLOW = "#FAFE4B" + const val LIPSTICK_RED = "#C0022F" + const val WATER_BLUE = "#0E87CC" + const val BROWN_GREY = "#8D8468" + const val VIBRANT_PURPLE = "#AD03DE" + const val BABY_GREEN = "#8CFF9E" + const val BARF_GREEN = "#94AC02" + const val EGGSHELL_BLUE = "#C4FFF7" + const val SANDY_YELLOW = "#FDEE73" + const val COOL_GREEN = "#33B864" + const val PALE = "#FFF9D0" + const val HOT_MAGENTA = "#F504C9" + const val GREYBLUE = "#77A1B5" + const val PURPLEY = "#8756E4" + const val BABY_SHIT_GREEN = "#889717" + const val BROWNISH_PINK = "#C27E79" + const val DARK_AQUAMARINE = "#017371" + const val DIARRHEA = "#9F8303" + const val LIGHT_MUSTARD = "#F7D560" + const val PALE_SKY_BLUE = "#BDF6FE" + const val TURTLE_GREEN = "#75B84F" + const val BRIGHT_OLIVE = "#9CBB04" + const val DARK_GREY_BLUE = "#29465B" + const val GREENY_BROWN = "#696006" + const val LEMON_GREEN = "#ADF802" + const val LIGHT_PERIWINKLE = "#C1C6FC" + const val SEAWEED_GREEN = "#35AD6B" + const val SUNSHINE_YELLOW = "#FFFD37" + const val UGLY_PURPLE = "#A442A0" + const val MEDIUM_PINK = "#F36196" + const val PUKE_BROWN = "#947706" + const val VERY_LIGHT_PINK = "#FFF4F2" + const val VIRIDIAN = "#1E9167" + const val BILE = "#B5C306" + const val FADED_YELLOW = "#FEFF7F" + const val VERY_PALE_GREEN = "#CFFDBC" + const val VIBRANT_GREEN = "#0ADD08" + const val BRIGHT_LIME = "#87FD05" + const val SPEARMINT = "#1EF876" + const val LIGHT_AQUAMARINE = "#7BFDC7" + const val LIGHT_SAGE = "#BCECAC" + const val YELLOWGREEN = "#BBF90F" + const val BABY_POO = "#AB9004" + const val DARK_SEAFOAM = "#1FB57A" + const val DEEP_TEAL = "#00555A" + const val HEATHER = "#A484AC" + const val RUST_ORANGE = "#C45508" + const val DIRTY_BLUE = "#3F829D" + const val FERN_GREEN = "#548D44" + const val BRIGHT_LILAC = "#C95EFB" + const val WEIRD_GREEN = "#3AE57F" + const val PEACOCK_BLUE = "#016795" + const val AVOCADO_GREEN = "#87A922" + const val FADED_ORANGE = "#F0944D" + const val GRAPE_PURPLE = "#5D1451" + const val HOT_GREEN = "#25FF29" + const val LIME_YELLOW = "#D0FE1D" + const val MANGO = "#FFA62B" + const val SHAMROCK = "#01B44C" + const val BUBBLEGUM = "#FF6CB5" + const val PURPLISH_BROWN = "#6B4247" + const val VOMIT_YELLOW = "#C7C10C" + const val PALE_CYAN = "#B7FFFA" + const val KEY_LIME = "#AEFF6E" + const val TOMATO_RED = "#EC2D01" + const val LIGHTGREEN = "#76FF7B" + const val MERLOT = "#730039" + const val NIGHT_BLUE = "#040348" + const val PURPLEISH_PINK = "#DF4EC8" + const val APPLE = "#6ECB3C" + const val BABY_POOP_GREEN = "#8F9805" + const val GREEN_APPLE = "#5EDC1F" + const val HELIOTROPE = "#D94FF5" + const val ALMOST_BLACK = "#070D0D" + const val COOL_BLUE = "#4984B8" + const val LEAFY_GREEN = "#51B73B" + const val MUSTARD_BROWN = "#AC7E04" + const val DUSK = "#4E5481" + const val DULL_BROWN = "#876E4B" + const val FROG_GREEN = "#58BC08" + const val VIVID_GREEN = "#2FEF10" + const val BRIGHT_LIGHT_GREEN = "#2DFE54" + const val FLURO_GREEN = "#0AFF02" + const val KIWI = "#9CEF43" + const val SEAWEED = "#18D17B" + const val NAVY_GREEN = "#35530A" + const val ULTRAMARINE_BLUE = "#1805DB" + const val IRIS = "#6258C4" + const val PASTEL_ORANGE = "#FF964F" + const val YELLOWISH_ORANGE = "#FFAB0F" + const val PERRYWINKLE = "#8F8CE7" + const val TEALISH = "#24BCA8" + const val DARK_PLUM = "#3F012C" + const val PEAR = "#CBF85F" + const val PINKISH_ORANGE = "#FF724C" + const val MIDNIGHT_PURPLE = "#280137" + const val LIGHT_URPLE = "#B36FF6" + const val DARK_MINT = "#48C072" + const val GREENISH_TAN = "#BCCB7A" + const val LIGHT_BURGUNDY = "#A8415B" + const val TURQUOISE_BLUE = "#06B1C4" + const val UGLY_PINK = "#CD7584" + const val SANDY = "#F1DA7A" + const val ELECTRIC_PINK = "#FF0490" + const val MUTED_PURPLE = "#805B87" + const val MID_GREEN = "#50A747" + const val GREYISH = "#A8A495" + const val NEON_YELLOW = "#CFFF04" + const val BANANA = "#FFFF7E" + const val CARNATION_PINK = "#FF7FA7" + const val TOMATO = "#EF4026" + const val SEA = "#3C9992" + const val MUDDY_BROWN = "#886806" + const val TURQUOISE_GREEN = "#04F489" + const val BUFF = "#FEF69E" + const val FAWN = "#CFAF7B" + const val MUTED_BLUE = "#3B719F" + const val PALE_ROSE = "#FDC1C5" + const val DARK_MINT_GREEN = "#20C073" + const val AMETHYST = "#9B5FC0" + const val CHESTNUT = "#742802" + const val SICK_GREEN = "#9DB92C" + const val PEA = "#A4BF20" + const val RUSTY_ORANGE = "#CD5909" + const val STONE = "#ADA587" + const val ROSE_RED = "#BE013C" + const val PALE_AQUA = "#B8FFEB" + const val DEEP_ORANGE = "#DC4D01" + const val EARTH = "#A2653E" + const val MOSSY_GREEN = "#638B27" + const val GRASSY_GREEN = "#419C03" + const val PALE_LIME_GREEN = "#B1FF65" + const val LIGHT_GREY_BLUE = "#9DBCD4" + const val PALE_GREY = "#FDFDFE" + const val ASPARAGUS = "#77AB56" + const val BLUEBERRY = "#464196" + const val PURPLE_RED = "#990147" + const val PALE_LIME = "#BEFD73" + const val GREENISH_TEAL = "#32BF84" + const val CARAMEL = "#AF6F09" + const val DEEP_MAGENTA = "#A0025C" + const val LIGHT_PEACH = "#FFD8B1" + const val MILK_CHOCOLATE = "#7F4E1E" + const val OCHER = "#BF9B0C" + const val OFF_GREEN = "#6BA353" + const val PURPLY_PINK = "#F075E6" + const val LIGHTBLUE = "#7BC8F6" + const val DUSKY_BLUE = "#475F94" + const val GOLDEN = "#F5BF03" + const val LIGHT_BEIGE = "#FFFEB6" + const val BUTTER_YELLOW = "#FFFD74" + const val DUSKY_PURPLE = "#895B7B" + const val FRENCH_BLUE = "#436BAD" + const val UGLY_YELLOW = "#D0C101" + const val GREENY_YELLOW = "#C6F808" + const val ORANGISH_RED = "#F43605" + const val SHAMROCK_GREEN = "#02C14D" + const val ORANGISH_BROWN = "#B25F03" + const val TREE_GREEN = "#2A7E19" + const val DEEP_VIOLET = "#490648" + const val GUNMETAL = "#536267" + const val CHERRY = "#CF0234" + const val SANDY_BROWN = "#C4A661" + const val WARM_GREY = "#978A84" + const val DARK_INDIGO = "#1F0954" + const val MIDNIGHT = "#03012D" + const val BLUEY_GREEN = "#2BB179" + const val GREY_PINK = "#C3909B" + const val SOFT_PURPLE = "#A66FB5" + const val BLOOD = "#770001" + const val BROWN_RED = "#922B05" + const val MEDIUM_GREY = "#7D7F7C" + const val BERRY = "#990F4B" + const val POO = "#8F7303" + const val PURPLEY_PINK = "#C83CB9" + const val LIGHT_SALMON = "#FEA993" + const val SNOT = "#ACBB0D" + const val EASTER_PURPLE = "#C071FE" + const val LIGHT_YELLOW_GREEN = "#CCFD7F" + const val DARK_NAVY_BLUE = "#00022E" + const val DRAB = "#828344" + const val LIGHT_ROSE = "#FFC5CB" + const val ROUGE = "#AB1239" + const val PURPLISH_RED = "#B0054B" + const val SLIME_GREEN = "#99CC04" + const val BABY_POOP = "#937C00" + const val IRISH_GREEN = "#019529" + const val DARK_NAVY = "#000435" + const val GREENY_BLUE = "#42B395" + const val LIGHT_PLUM = "#9D5783" + const val PINKISH_GREY = "#C8ACA9" + const val DIRTY_ORANGE = "#C87606" + const val RUST_RED = "#AA2704" + const val PALE_LILAC = "#E4CBFF" + const val ORANGEY_RED = "#FA4224" + const val PRIMARY_BLUE = "#0804F9" + const val KERMIT_GREEN = "#5CB200" + const val BROWNISH_PURPLE = "#76424E" + const val MURKY_GREEN = "#6C7A0E" + const val WHEAT = "#FBDD7E" + const val VERY_DARK_PURPLE = "#2A0134" + const val BOTTLE_GREEN = "#044A05" + const val WATERMELON = "#FD4659" + const val DEEP_SKY_BLUE = "#0D75F8" + const val FIRE_ENGINE_RED = "#FE0002" + const val YELLOW_OCHRE = "#CB9D06" + const val PUMPKIN_ORANGE = "#FB7D07" + const val PALE_OLIVE = "#B9CC81" + const val LIGHT_LILAC = "#EDC8FF" + const val LIGHTISH_GREEN = "#61E160" + const val CAROLINA_BLUE = "#8AB8FE" + const val MULBERRY = "#920A4E" + const val SHOCKING_PINK = "#FE02A2" + const val AUBURN = "#9A3001" + const val BRIGHT_LIME_GREEN = "#65FE08" + const val CELADON = "#BEFDB7" + const val PINKISH_BROWN = "#B17261" + const val POO_BROWN = "#885F01" + const val BRIGHT_SKY_BLUE = "#02CCFE" + const val CELERY = "#C1FD95" + const val DIRT_BROWN = "#836539" + const val STRAWBERRY = "#FB2943" + const val DARK_LIME = "#84B701" + const val COPPER = "#B66325" + const val MEDIUM_BROWN = "#7F5112" + const val MUTED_GREEN = "#5FA052" + const val BRIGHT_AQUA = "#0BF9EA" + const val BRIGHT_LAVENDER = "#C760FF" + const val IVORY = "#FFFFCB" + const val VERY_LIGHT_PURPLE = "#F6CEFC" + const val LIGHT_NAVY = "#155084" + const val PINK_RED = "#F5054F" + const val OLIVE_BROWN = "#645403" + const val POOP_BROWN = "#7A5901" + const val MUSTARD_GREEN = "#A8B504" + const val OCEAN_GREEN = "#3D9973" + const val VERY_DARK_BLUE = "#000133" + const val DUSTY_GREEN = "#76A973" + const val LIGHT_NAVY_BLUE = "#2E5A88" + const val MINTY_GREEN = "#0BF77D" + const val ADOBE = "#BD6C48" + const val BARNEY = "#AC1DB8" + const val JADE_GREEN = "#2BAF6A" + const val BRIGHT_LIGHT_BLUE = "#26F7FD" + const val LIGHT_LIME = "#AEFD6C" + const val DARK_KHAKI = "#9B8F55" + const val ORANGE_YELLOW = "#FFAD01" + const val OCRE = "#C69C04" + const val MAIZE = "#F4D054" + const val FADED_PINK = "#DE9DAC" + const val BRITISH_RACING_GREEN = "#05480D" + const val SANDSTONE = "#C9AE74" + const val MUD_BROWN = "#60460F" + const val LIGHT_SEA_GREEN = "#98F6B0" + const val ROBIN_EGG_BLUE = "#8AF1FE" + const val AQUA_MARINE = "#2EE8BB" + const val DARK_SEA_GREEN = "#11875D" + const val SOFT_PINK = "#FDB0C0" + const val ORANGEY_BROWN = "#B16002" + const val CHERRY_RED = "#F7022A" + const val BURNT_YELLOW = "#D5AB09" + const val BROWNISH_GREY = "#86775F" + const val CAMEL = "#C69F59" + const val PURPLISH_GREY = "#7A687F" + const val MARINE = "#042E60" + const val GREYISH_PINK = "#C88D94" + const val PALE_TURQUOISE = "#A5FBD5" + const val PASTEL_YELLOW = "#FFFE71" + const val BLUEY_PURPLE = "#6241C7" + const val CANARY_YELLOW = "#FFFE40" + const val FADED_RED = "#D3494E" + const val SEPIA = "#985E2B" + const val COFFEE = "#A6814C" + const val BRIGHT_MAGENTA = "#FF08E8" + const val MOCHA = "#9D7651" + const val ECRU = "#FEFFCA" + const val PURPLEISH = "#98568D" + const val CRANBERRY = "#9E003A" + const val DARKISH_GREEN = "#287C37" + const val BROWN_ORANGE = "#B96902" + const val DUSKY_ROSE = "#BA6873" + const val MELON = "#FF7855" + const val SICKLY_GREEN = "#94B21C" + const val SILVER = "#C5C9C7" + const val PURPLY_BLUE = "#661AEE" + const val PURPLEISH_BLUE = "#6140EF" + const val HOSPITAL_GREEN = "#9BE5AA" + const val SHIT_BROWN = "#7B5804" + const val MID_BLUE = "#276AB3" + const val AMBER = "#FEB308" + const val EASTER_GREEN = "#8CFD7E" + const val SOFT_BLUE = "#6488EA" + const val CERULEAN_BLUE = "#056EEE" + const val GOLDEN_BROWN = "#B27A01" + const val BRIGHT_TURQUOISE = "#0FFEF9" + const val RED_PINK = "#FA2A55" + const val RED_PURPLE = "#820747" + const val GREYISH_BROWN = "#7A6A4F" + const val VERMILLION = "#F4320C" + const val RUSSET = "#A13905" + const val STEEL_GREY = "#6F828A" + const val LIGHTER_PURPLE = "#A55AF4" + const val BRIGHT_VIOLET = "#AD0AFD" + const val PRUSSIAN_BLUE = "#004577" + const val SLATE_GREEN = "#658D6D" + const val DIRTY_PINK = "#CA7B80" + const val DARK_BLUE_GREEN = "#005249" + const val PINE = "#2B5D34" + const val YELLOWY_GREEN = "#BFF128" + const val DARK_GOLD = "#B59410" + const val BLUISH = "#2976BB" + const val DARKISH_BLUE = "#014182" + const val DULL_RED = "#BB3F3F" + const val PINKY_RED = "#FC2647" + const val BRONZE = "#A87900" + const val PALE_TEAL = "#82CBB2" + const val MILITARY_GREEN = "#667C3E" + const val BARBIE_PINK = "#FE46A5" + const val BUBBLEGUM_PINK = "#FE83CC" + const val PEA_SOUP_GREEN = "#94A617" + const val DARK_MUSTARD = "#A88905" + const val SHIT = "#7F5F00" + const val MEDIUM_PURPLE = "#9E43A2" + const val VERY_DARK_GREEN = "#062E03" + const val DIRT = "#8A6E45" + const val DUSKY_PINK = "#CC7A8B" + const val RED_VIOLET = "#9E0168" + const val LEMON_YELLOW = "#FDFF38" + const val PISTACHIO = "#C0FA8B" + const val DULL_YELLOW = "#EEDC5B" + const val DARK_LIME_GREEN = "#7EBD01" + const val DENIM_BLUE = "#3B5B92" + const val TEAL_BLUE = "#01889F" + const val LIGHTISH_BLUE = "#3D7AFD" + const val PURPLEY_BLUE = "#5F34E7" + const val LIGHT_INDIGO = "#6D5ACF" + const val SWAMP_GREEN = "#748500" + const val BROWN_GREEN = "#706C11" + const val DARK_MAROON = "#3C0008" + const val HOT_PURPLE = "#CB00F5" + const val DARK_FOREST_GREEN = "#002D04" + const val FADED_BLUE = "#658CBB" + const val DRAB_GREEN = "#749551" + const val LIGHT_LIME_GREEN = "#B9FF66" + const val SNOT_GREEN = "#9DC100" + const val YELLOWISH = "#FAEE66" + const val LIGHT_BLUE_GREEN = "#7EFBB3" + const val BORDEAUX = "#7B002C" + const val LIGHT_MAUVE = "#C292A1" + const val OCEAN = "#017B92" + const val MARIGOLD = "#FCC006" + const val MUDDY_GREEN = "#657432" + const val DULL_ORANGE = "#D8863B" + const val STEEL = "#738595" + const val ELECTRIC_PURPLE = "#AA23FF" + const val FLUORESCENT_GREEN = "#08FF08" + const val YELLOWISH_BROWN = "#9B7A01" + const val BLUSH = "#F29E8E" + const val SOFT_GREEN = "#6FC276" + const val BRIGHT_ORANGE = "#FF5B00" + const val LEMON = "#FDFF52" + const val PURPLE_GREY = "#866F85" + const val ACID_GREEN = "#8FFE09" + const val PALE_LAVENDER = "#EECFFE" + const val VIOLET_BLUE = "#510AC9" + const val LIGHT_FOREST_GREEN = "#4F9153" + const val BURNT_RED = "#9F2305" + const val KHAKI_GREEN = "#728639" + const val CERISE = "#DE0C62" + const val FADED_PURPLE = "#916E99" + const val APRICOT = "#FFB16D" + const val DARK_OLIVE_GREEN = "#3C4D03" + const val GREY_BROWN = "#7F7053" + const val GREEN_GREY = "#77926F" + const val TRUE_BLUE = "#010FCC" + const val PALE_VIOLET = "#CEAEFA" + const val PERIWINKLE_BLUE = "#8F99FB" + const val LIGHT_SKY_BLUE = "#C6FCFF" + const val BLURPLE = "#5539CC" + const val GREEN_BROWN = "#544E03" + const val BLUEGREEN = "#017A79" + const val BRIGHT_TEAL = "#01F9C6" + const val BROWNISH_YELLOW = "#C9B003" + const val PEA_SOUP = "#929901" + const val FOREST = "#0B5509" + const val BARNEY_PURPLE = "#A00498" + const val ULTRAMARINE = "#2000B1" + const val PURPLISH = "#94568C" + const val PUKE_YELLOW = "#C2BE0E" + const val BLUISH_GREY = "#748B97" + const val DARK_PERIWINKLE = "#665FD1" + const val DARK_LILAC = "#9C6DA5" + const val REDDISH = "#C44240" + const val LIGHT_MAROON = "#A24857" + const val DUSTY_PURPLE = "#825F87" + const val TERRA_COTTA = "#C9643B" + const val AVOCADO = "#90B134" + const val MARINE_BLUE = "#01386A" + const val TEAL_GREEN = "#25A36F" + const val SLATE_GREY = "#59656D" + const val LIGHTER_GREEN = "#75FD63" + const val ELECTRIC_GREEN = "#21FC0D" + const val DUSTY_BLUE = "#5A86AD" + const val GOLDEN_YELLOW = "#FEC615" + const val BRIGHT_YELLOW = "#FFFD01" + const val LIGHT_LAVENDER = "#DFC5FE" + const val UMBER = "#B26400" + const val POOP = "#7F5E00" + const val DARK_PEACH = "#DE7E5D" + const val JUNGLE_GREEN = "#048243" + const val EGGSHELL = "#FFFFD4" + const val DENIM = "#3B638C" + const val YELLOW_BROWN = "#B79400" + const val DULL_PURPLE = "#84597E" + const val CHOCOLATE_BROWN = "#411900" + const val WINE_RED = "#7B0323" + const val NEON_BLUE = "#04D9FF" + const val DIRTY_GREEN = "#667E2C" + const val LIGHT_TAN = "#FBEEAC" + const val ICE_BLUE = "#D7FFFE" + const val CADET_BLUE = "#4E7496" + const val DARK_MAUVE = "#874C62" + const val VERY_LIGHT_BLUE = "#D5FFFF" + const val GREY_PURPLE = "#826D8C" + const val PASTEL_PINK = "#FFBACD" + const val VERY_LIGHT_GREEN = "#D1FFBD" + const val DARK_SKY_BLUE = "#448EE4" + const val EVERGREEN = "#05472A" + const val DULL_PINK = "#D5869D" + const val AUBERGINE = "#3D0734" + const val MAHOGANY = "#4A0100" + const val REDDISH_ORANGE = "#F8481C" + const val DEEP_GREEN = "#02590F" + const val VOMIT_GREEN = "#89A203" + const val PURPLE_PINK = "#E03FD8" + const val DUSTY_PINK = "#D58A94" + const val FADED_GREEN = "#7BB274" + const val CAMO_GREEN = "#526525" + const val PINKY_PURPLE = "#C94CBE" + const val PINK_PURPLE = "#DB4BDA" + const val BROWNISH_RED = "#9E3623" + const val DARK_ROSE = "#B5485D" + const val MUD = "#735C12" + const val BROWNISH = "#9C6D57" + const val EMERALD_GREEN = "#028F1E" + const val PALE_BROWN = "#B1916E" + const val DULL_BLUE = "#49759C" + const val BURNT_UMBER = "#A0450E" + const val MEDIUM_GREEN = "#39AD48" + const val CLAY = "#B66A50" + const val LIGHT_AQUA = "#8CFFDB" + const val LIGHT_OLIVE_GREEN = "#A4BE5C" + const val BROWNISH_ORANGE = "#CB7723" + const val DARK_AQUA = "#05696B" + const val PURPLISH_PINK = "#CE5DAE" + const val DARK_SALMON = "#C85A53" + const val GREENISH_GREY = "#96AE8D" + const val JADE = "#1FA774" + const val UGLY_GREEN = "#7A9703" + const val DARK_BEIGE = "#AC9362" + const val EMERALD = "#01A049" + const val PALE_RED = "#D9544D" + const val LIGHT_MAGENTA = "#FA5FF7" + const val SKY = "#82CAFC" + const val LIGHT_CYAN = "#ACFFFC" + const val YELLOW_ORANGE = "#FCB001" + const val REDDISH_PURPLE = "#910951" + const val REDDISH_PINK = "#FE2C54" + const val ORCHID = "#C875C4" + const val DIRTY_YELLOW = "#CDC50A" + const val ORANGE_RED = "#FD411E" + const val DEEP_RED = "#9A0200" + const val ORANGE_BROWN = "#BE6400" + const val COBALT_BLUE = "#030AA7" + const val NEON_PINK = "#FE019A" + const val ROSE_PINK = "#F7879A" + const val GREYISH_PURPLE = "#887191" + const val RASPBERRY = "#B00149" + const val AQUA_GREEN = "#12E193" + const val SALMON_PINK = "#FE7B7C" + const val TANGERINE = "#FF9408" + const val BROWNISH_GREEN = "#6A6E09" + const val RED_BROWN = "#8B2E16" + const val GREENISH_BROWN = "#696112" + const val PUMPKIN = "#E17701" + const val PINE_GREEN = "#0A481E" + const val CHARCOAL = "#343837" + const val BABY_PINK = "#FFB7CE" + const val CORNFLOWER = "#6A79F7" + const val BLUE_VIOLET = "#5D06E9" + const val CHOCOLATE = "#3D1C02" + const val GREYISH_GREEN = "#82A67D" + const val SCARLET = "#BE0119" + const val GREEN_YELLOW = "#C9FF27" + const val DARK_OLIVE = "#373E02" + const val SIENNA = "#A9561E" + const val PASTEL_PURPLE = "#CAA0FF" + const val TERRACOTTA = "#CA6641" + const val AQUA_BLUE = "#02D8E9" + const val SAGE_GREEN = "#88B378" + const val BLOOD_RED = "#980002" + const val DEEP_PINK = "#CB0162" + const val GRASS = "#5CAC2D" + const val MOSS = "#769958" + const val PASTEL_BLUE = "#A2BFFE" + const val BLUISH_GREEN = "#10A674" + const val GREEN_BLUE = "#06B48B" + const val DARK_TAN = "#AF884A" + const val GREENISH_BLUE = "#0B8B87" + const val PALE_ORANGE = "#FFA756" + const val VOMIT = "#A2A415" + const val FORREST_GREEN = "#154406" + const val DARK_LAVENDER = "#856798" + const val DARK_VIOLET = "#34013F" + const val PURPLE_BLUE = "#632DE9" + const val DARK_CYAN = "#0A888A" + const val OLIVE_DRAB = "#6F7632" + const val PINKISH = "#D46A7E" + const val COBALT = "#1E488F" + const val NEON_PURPLE = "#BC13FE" + const val LIGHT_TURQUOISE = "#7EF4CC" + const val APPLE_GREEN = "#76CD26" + const val DULL_GREEN = "#74A662" + const val WINE = "#80013F" + const val POWDER_BLUE = "#B1D1FC" + const val OFF_WHITE = "#FFFFE4" + const val ELECTRIC_BLUE = "#0652FF" + const val DARK_TURQUOISE = "#045C5A" + const val BLUE_PURPLE = "#5729CE" + const val AZURE = "#069AF3" + const val BRIGHT_RED = "#FF000D" + const val PINKISH_RED = "#F10C45" + const val CORNFLOWER_BLUE = "#5170D7" + const val LIGHT_OLIVE = "#ACBF69" + const val GRAPE = "#6C3461" + const val GREYISH_BLUE = "#5E819D" + const val PURPLISH_BLUE = "#601EF9" + const val YELLOWISH_GREEN = "#B0DD16" + const val GREENISH_YELLOW = "#CDFD02" + const val MEDIUM_BLUE = "#2C6FBB" + const val DUSTY_ROSE = "#C0737A" + const val LIGHT_VIOLET = "#D6B4FC" + const val MIDNIGHT_BLUE = "#020035" + const val BLUISH_PURPLE = "#703BE7" + const val RED_ORANGE = "#FD3C06" + const val DARK_MAGENTA = "#960056" + const val GREENISH = "#40A368" + const val OCEAN_BLUE = "#03719C" + const val CORAL = "#FC5A50" + const val CREAM = "#FFFFC2" + const val REDDISH_BROWN = "#7F2B0A" + const val BURNT_SIENNA = "#B04E0F" + const val BRICK = "#A03623" + const val SAGE = "#87AE73" + const val GREY_GREEN = "#789B73" + const val WHITE = "#FFFFFF" + const val MOSS_GREEN = "#658B38" + const val STEEL_BLUE = "#5A7D9A" + const val EGGPLANT = "#380835" + const val LIGHT_YELLOW = "#FFFE7A" + const val LEAF_GREEN = "#5CA904" + const val LIGHT_GREY = "#D8DCD6" + const val PUKE = "#A5A502" + const val PINKISH_PURPLE = "#D648D7" + const val SEA_BLUE = "#047495" + const val PALE_PURPLE = "#B790D4" + const val SLATE_BLUE = "#5B7C99" + const val BLUE_GREY = "#607C8E" + const val HUNTER_GREEN = "#0B4008" + const val FUCHSIA = "#ED0DD9" + const val CRIMSON = "#8C000F" + const val PALE_YELLOW = "#FFFF84" + const val OCHRE = "#BF9005" + const val MUSTARD_YELLOW = "#D2BD0A" + const val LIGHT_RED = "#FF474C" + const val CERULEAN = "#0485D1" + const val PALE_PINK = "#FFCFDC" + const val DEEP_BLUE = "#040273" + const val RUST = "#A83C09" + const val LIGHT_TEAL = "#90E4C1" + const val SLATE = "#516572" + const val GOLDENROD = "#FAC205" + const val DARK_YELLOW = "#D5B60A" + const val DARK_GREY = "#363737" + const val ARMY_GREEN = "#4B5D16" + const val GREY_BLUE = "#6B8BA4" + const val SEAFOAM = "#80F9AD" + const val PUCE = "#A57E52" + const val SPRING_GREEN = "#A9F971" + const val DARK_ORANGE = "#C65102" + const val SAND = "#E2CA76" + const val PASTEL_GREEN = "#B0FF9D" + const val MINT = "#9FFEB0" + const val LIGHT_ORANGE = "#FDAA48" + const val BRIGHT_PINK = "#FE01B1" + const val CHARTREUSE = "#C1F80A" + const val DEEP_PURPLE = "#36013F" + const val DARK_BROWN = "#341C02" + const val TAUPE = "#B9A281" + const val PEA_GREEN = "#8EAB12" + const val PUKE_GREEN = "#9AAE07" + const val KELLY_GREEN = "#02AB2E" + const val SEAFOAM_GREEN = "#7AF9AB" + const val BLUE_GREEN = "#137E6D" + const val KHAKI = "#AAA662" + const val BURGUNDY = "#610023" + const val DARK_TEAL = "#014D4E" + const val BRICK_RED = "#8F1402" + const val ROYAL_PURPLE = "#4B006E" + const val PLUM = "#580F41" + const val MINT_GREEN = "#8FFF9F" + const val GOLD = "#DBB40C" + const val BABY_BLUE = "#A2CFFE" + const val YELLOW_GREEN = "#C0FB2D" + const val BRIGHT_PURPLE = "#BE03FD" + const val DARK_RED = "#840000" + const val PALE_BLUE = "#D0FEFE" + const val GRASS_GREEN = "#3F9B0B" + const val NAVY = "#01153E" + const val AQUAMARINE = "#04D8B2" + const val BURNT_ORANGE = "#C04E01" + const val NEON_GREEN = "#0CFF0C" + const val BRIGHT_BLUE = "#0165FC" + const val ROSE = "#CF6275" + const val LIGHT_PINK = "#FFD1DF" + const val MUSTARD = "#CEB301" + const val INDIGO = "#380282" + const val LIME = "#AAFF32" + const val SEA_GREEN = "#53FCA1" + const val PERIWINKLE = "#8E82FE" + const val DARK_PINK = "#CB416B" + const val OLIVE_GREEN = "#677A04" + const val PEACH = "#FFB07C" + const val PALE_GREEN = "#C7FDB5" + const val LIGHT_BROWN = "#AD8150" + const val HOT_PINK = "#FF028D" + const val BLACK = "#000000" + const val LILAC = "#CEA2FD" + const val NAVY_BLUE = "#001146" + const val ROYAL_BLUE = "#0504AA" + const val BEIGE = "#E6DAA6" + const val SALMON = "#FF796C" + const val OLIVE = "#6E750E" + const val MAROON = "#650021" + const val BRIGHT_GREEN = "#01FF07" + const val DARK_PURPLE = "#35063E" + const val MAUVE = "#AE7181" + const val FOREST_GREEN = "#06470C" + const val AQUA = "#13EAC9" + const val CYAN = "#00FFFF" + const val TAN = "#D1B26F" + const val DARK_BLUE = "#00035B" + const val LAVENDER = "#C79FEF" + const val TURQUOISE = "#06C2AC" + const val DARK_GREEN = "#033500" + const val VIOLET = "#9A0EEA" + const val LIGHT_PURPLE = "#BF77F6" + const val LIME_GREEN = "#89FE05" + const val GREY = "#929591" + const val SKY_BLUE = "#75BBFD" + const val YELLOW = "#FFFF14" + const val MAGENTA = "#C20078" + const val LIGHT_GREEN = "#96F97B" + const val ORANGE = "#F97306" + const val TEAL = "#029386" + const val LIGHT_BLUE = "#95D0FC" + const val RED = "#E50000" + const val BROWN = "#653700" + const val PINK = "#FF81C0" + const val BLUE = "#0343DF" + const val GREEN = "#15B01A" + const val PURPLE = "#7E1E9C" +} diff --git a/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/plotExtensions.kt b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/plotExtensions.kt new file mode 100644 index 00000000..e99ccbfc --- /dev/null +++ b/plotly/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/plotExtensions.kt @@ -0,0 +1,84 @@ +package space.kscience.plotly + +import space.kscience.plotly.models.* + + +public inline fun Plot.histogram(block: Histogram.() -> Unit): Histogram { + val trace = Histogram(block) + traces(trace) + return trace +} + +public inline fun Plot.histogram2d(block: Histogram2D.() -> Unit): Histogram2D { + val trace = Histogram2D(block) + traces(trace) + return trace +} + +public inline fun Plot.histogram2dcontour(block: Histogram2DContour.() -> Unit): Histogram2DContour { + val trace = Histogram2DContour(block) + traces(trace) + return trace +} + +public inline fun Plot.pie(block: Pie.() -> Unit): Pie { + val trace = Pie(block) + traces(trace) + return trace +} + +public inline fun Plot.contour(block: Contour.() -> Unit): Contour { + val trace = Contour(block) + traces(trace) + return trace +} + +public inline fun Plot.scatter(block: Scatter.() -> Unit): Scatter { + val trace = Scatter(block) + traces(trace) + return trace +} + +public inline fun Plot.heatmap(block: Heatmap.() -> Unit): Heatmap { + val trace = Heatmap(block) + traces(trace) + return trace +} + +public inline fun Plot.box(block: Box.() -> Unit): Box { + val trace = Box(block) + traces(trace) + return trace +} + +public inline fun Plot.violin(block: Violin.() -> Unit): Violin { + val trace = Violin(block) + traces(trace) + return trace +} + +public inline fun Plot.bar(block: Bar.() -> Unit): Bar { + val trace = Bar(block) + traces(trace) + return trace +} + +public inline fun Plot.table(block: Table.() -> Unit): Table { + val trace = Table(block) + traces(trace) + return trace +} + +public inline fun Plot.candlestick(block: CandleStick.() -> Unit): CandleStick { + val trace = CandleStick(block) + traces(trace) + return trace +} + +public fun Plot.text(block: Text.() -> Unit) { + layout.annotation(block) +} + +public fun Plot.shape(block: Shape.() -> Unit) { + layout.figure(block) +} diff --git a/plotly/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyConnect.kt b/plotly/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyConnect.kt new file mode 100644 index 00000000..cf2d6832 --- /dev/null +++ b/plotly/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyConnect.kt @@ -0,0 +1,167 @@ +package space.kscience.plotly + +import kotlinx.browser.document +import kotlinx.browser.window +import org.w3c.dom.* +import org.w3c.dom.url.URL +import org.w3c.fetch.RequestInit +import kotlin.js.Promise +import kotlin.js.json + +@JsExport +public object PlotlyConnect { + + /** + * Wait for the Plotly library to be loaded + */ + private fun withPlotly(action: PlotlyJs.() -> Unit) { + if (jsTypeOf(PlotlyJs) !== "undefined") { + action(PlotlyJs); + } else { + val promiseOfPlotly: Promise<PlotlyJs> = window.asDynamic().promiseOfPlotly as Promise<PlotlyJs> + if (jsTypeOf(promiseOfPlotly) != "undefined") { + promiseOfPlotly.then { action(PlotlyJs) } + } else { + console.warn("Plotly not defined. Loading the script from CDN") + window.asDynamic().promiseOfPlotly = Promise<PlotlyJs> { resolve, reject -> + val plotlyLoaderScript = document.createElement("script") as HTMLScriptElement + plotlyLoaderScript.src = "https://cdn.plot.ly/plotly-2.29.0.min.js" + plotlyLoaderScript.type = "text/javascript" + plotlyLoaderScript.onload = { + resolve(PlotlyJs) + action(PlotlyJs) + } + plotlyLoaderScript.onerror = { error, _, _, _, _ -> + console.error(error); + reject(error as Throwable) + } + document.head?.appendChild(plotlyLoaderScript); + } + } + } + } + + /** + * Request and parse json from given address + * @param url {URL} + * @param callback + */ + private fun getJSON(url: URL, callback: (dynamic) -> Unit) { + try { + window.fetch( + url, + RequestInit( + method = "GET", + headers = json("Accept" to "application/json") + ) + ).then { response -> + if (!response.ok) { + error("Fetch request failed with error: ${response.statusText}") + } else { + response.json().then(callback) + } + }.catch { error -> console.log(error) } + } catch (e: Exception) { + window.alert("Fetch of plot data failed with error: $e") + } + } + + public fun makePlot( + graphDiv: Element, + data: Array<dynamic>, + layout: dynamic, + config: dynamic, + ) { + withPlotly { newPlot(graphDiv, data, layout, config) } + } + + /** + * Create a plot taking data from given url + * @param id {string} element id for plot + * @param from {URL} json server url + * @param config {object} plotly configuration + */ + + public fun createPlotFrom(id: String, from: URL, config: dynamic = {}) { + getJSON(from) { json -> + val element = document.getElementById(id) as HTMLElement + withPlotly { newPlot(element, json.data, json.layout, config) } + } + } + + /** + * Update a plot taking data from given url + * @param id {string} element id for plot + * @param from {URL} json server url + * @return {JSON} + */ + public fun updatePlotFrom(id: String, from: URL) { + getJSON(from) { json -> + val element = document.getElementById(id) as HTMLElement + withPlotly { react(element, json.data, json.layout) } + } + } + + /** + * Start pull updates with regular requests from client side + * @param id {string} + * @param from + * @param millis + */ + public fun startPull(id: String, from: URL, millis: Int) { + window.setInterval({ updatePlotFrom(id, from) }, millis) + } + + /** + * Start push updates via websocket + * @param id {string} element id for plot + * @param ws {URL} a websocket address + */ + public fun startPush(id: String, ws: String) { + val element = document.getElementById(id) as HTMLElement + val socket = WebSocket(ws) + + socket.onopen = { + console.log("[Plotly.kt] A connection for plot with id = $id with server established on $ws") + } + + socket.onclose = { event -> + event as CloseEvent + if (event.wasClean) { + console.log("The connection with server is closed") + } else { + console.log("The connection with server is broken") // Server process is dead + } + console.log("Code: ${event.code} case: ${event.reason}") + } + + socket.onerror = { error -> + error as ErrorEvent + console.error("Plotly push update error: " + error.message) + socket.close() + } + + socket.onmessage = { event -> + val json: dynamic = JSON.parse(event.data.toString()) + if (json.plotId === id) { + if (json.contentType === "layout") { + withPlotly { relayout(element, json.content) } + } else if (json.contentType === "trace") { + withPlotly { restyle(element, json.content, json.trace) } + } + } + } + + //gracefully close the socket just in case + window.onbeforeunload = { + console.log("Gracefully closing socket") + socket.close() + null + } + } +} + +public fun main() { + window.asDynamic().plotlyConnect = PlotlyConnect + window.asDynamic().Plotly = PlotlyJs +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyElement.kt b/plotly/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyElement.kt new file mode 100644 index 00000000..329c1776 --- /dev/null +++ b/plotly/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyElement.kt @@ -0,0 +1,106 @@ +package space.kscience.plotly + +import kotlinx.html.TagConsumer +import kotlinx.html.div +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.decodeFromDynamic +import kotlinx.serialization.json.encodeToDynamic +import org.w3c.dom.Element +import org.w3c.dom.HTMLElement +import org.w3c.dom.events.MouseEvent +import space.kscience.dataforge.meta.MetaSerializer +import space.kscience.dataforge.meta.Scheme +import space.kscience.dataforge.meta.Value +import space.kscience.dataforge.names.asName +import space.kscience.dataforge.names.firstOrNull +import space.kscience.dataforge.names.startsWith +import space.kscience.plotly.events.PlotlyEvent +import space.kscience.plotly.events.PlotlyEventListenerType +import space.kscience.plotly.events.PlotlyEventPoint + +@OptIn(ExperimentalSerializationApi::class) +private fun Scheme.toDynamic(): dynamic = Json.encodeToDynamic(MetaSerializer, meta) + +private fun List<Scheme>.toDynamic(): Array<dynamic> = map { it.toDynamic() }.toTypedArray() + +/** + * Attach a plot to this element or update the existing plot + */ +public fun Element.plot(plotlyConfig: PlotlyConfig = PlotlyConfig(), plot: Plot) { + val tracesData = plot.data.toDynamic() + val layout = plot.layout.toDynamic() + +// console.info(""" +// Plotly.react( +// '$this', +// ${JSON.stringify(tracesData)}, +// ${JSON.stringify(layout)} +// ); +// """.trimIndent()) + + PlotlyJs.react(this, tracesData, layout, plotlyConfig.toDynamic()) + + plot.meta.onChange(this) { name -> + if (name.startsWith(plot::layout.name.asName())) { + PlotlyJs.relayout(this@plot, plot.layout.toDynamic()) + } else if (name.firstOrNull()?.body == "data") { + val traceName = name.firstOrNull()!! + val traceIndex = traceName.index?.toInt() ?: 0 + val traceData = plot.data[traceIndex].toDynamic() + + Plotly.coordinateNames.forEach { coordinate -> + val data = traceData[coordinate] + if (traceData[coordinate] != null) { + traceData[coordinate] = arrayOf(data) + } + } + + PlotlyJs.restyle(this@plot, traceData, arrayOf(traceIndex)) + } + } +} + +@Deprecated("Change arguments positions", ReplaceWith("plot(plotlyConfig, plot)")) +public fun Element.plot(plot: Plot, plotlyConfig: PlotlyConfig = PlotlyConfig()): Unit = plot(plotlyConfig, plot) + +/** + * Create a plot in this element + */ +public inline fun Element.plot(plotlyConfig: PlotlyConfig = PlotlyConfig(), plotBuilder: Plot.() -> Unit) { + plot(plotlyConfig, Plot().apply(plotBuilder)) +} + +public class PlotlyElement(public val div: HTMLElement) + +/** + * Create a div element and render plot in it + */ +public fun TagConsumer<HTMLElement>.plotDiv( + plotlyConfig: PlotlyConfig = PlotlyConfig(), + plot: Plot, +): PlotlyElement = PlotlyElement(div("plotly-kt-plot").apply { plot(plotlyConfig, plot) }) + +/** + * Render plot in the HTML element using direct plotly API. + */ +public inline fun TagConsumer<HTMLElement>.plotDiv( + plotlyConfig: PlotlyConfig = PlotlyConfig(), + plotBuilder: Plot.() -> Unit, +): PlotlyElement = PlotlyElement(div("plotly-kt-plot").apply { plot(plotlyConfig, plotBuilder) }) + +@OptIn(ExperimentalSerializationApi::class) +public fun PlotlyElement.on(eventType: PlotlyEventListenerType, block: MouseEvent.(PlotlyEvent) -> Unit) { + div.asDynamic().on(eventType.eventType) { event: PlotMouseEvent -> + val eventData = PlotlyEvent(event.points.map { + PlotlyEventPoint( + curveNumber = it.curveNumber as Int, + pointNumber = it.pointNumber as? Int, + x = Value.of(it.x), + y = Value.of(it.y), + data = Json.decodeFromDynamic(it.data) + ) + }) + event.event.block(eventData) + } +} diff --git a/plotly/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyJs.kt b/plotly/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyJs.kt new file mode 100644 index 00000000..b5dc4a4d --- /dev/null +++ b/plotly/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyJs.kt @@ -0,0 +1,56 @@ +package space.kscience.plotly + +import org.w3c.dom.Element +import org.w3c.dom.events.MouseEvent +import kotlin.js.Promise + +public external interface ToImgOpts { + public var format: String /* 'jpeg' | 'png' | 'webp' | 'svg' */ + public var width: Number + public var height: Number +} + +public external interface DownloadImgOpts { + public var format: String /* 'jpeg' | 'png' | 'webp' | 'svg' */ + public var width: Number + public var height: Number + public var filename: String +} + + +@JsName("Plotly") +@JsModule("plotly.js/dist/plotly.js") +@JsNonModule +public external object PlotlyJs { + public fun newPlot( + graphDiv: Element, + data: Array<dynamic> = definedExternally, + layout: dynamic = definedExternally, + config: dynamic = definedExternally + ) + + public fun react( + graphDiv: Element, + data: dynamic = definedExternally, + layout: dynamic = definedExternally, + config: dynamic = definedExternally + ) + + public fun update( + graphDiv: Element, + data: dynamic = definedExternally, + layout: dynamic = definedExternally + ) + + public fun restyle(graphDiv: Element, update: dynamic, traceIndices: dynamic = definedExternally) + public fun relayout(graphDiv: Element, update: dynamic) + + public fun toImage(root: Element, opts: ToImgOpts): Promise<String> + public fun downloadImage(root: Element, opts: DownloadImgOpts): Promise<String> +} + + +public external interface PlotMouseEvent { + public val points : Array<dynamic> + public val event: MouseEvent +} diff --git a/plotly/plotlykt-core/src/jsMain/ts/Iterable.ts.kt b/plotly/plotlykt-core/src/jsMain/ts/Iterable.ts.kt new file mode 100644 index 00000000..197785c5 --- /dev/null +++ b/plotly/plotlykt-core/src/jsMain/ts/Iterable.ts.kt @@ -0,0 +1,31 @@ +@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", "EXTERNAL_DELEGATION") + +import kotlin.js.* +import kotlin.js.Json +import org.khronos.webgl.* +import org.w3c.dom.* +import org.w3c.dom.events.* +import org.w3c.dom.parsing.* +import org.w3c.dom.svg.* +import org.w3c.dom.url.* +import org.w3c.fetch.* +import org.w3c.files.* +import org.w3c.notifications.* +import org.w3c.performance.* +import org.w3c.workers.* +import org.w3c.xhr.* + +external interface IteratorResult<T> { + var done: Boolean + var value: T +} + +external interface TsStdLib_Iterator<T> { + fun next(value: Any? = definedExternally): IteratorResult<T> + val `return`: ((value: Any? /* = null */) -> IteratorResult<T>)? + get() = definedExternally + val `throw`: ((e: Any? /* = null */) -> IteratorResult<T>)? + get() = definedExternally +} + +external interface IterableIterator<T> : TsStdLib_Iterator<T> \ No newline at end of file diff --git a/plotly/plotlykt-core/src/jsMain/ts/Plotly.d.ts b/plotly/plotlykt-core/src/jsMain/ts/Plotly.d.ts new file mode 100644 index 00000000..2b015930 --- /dev/null +++ b/plotly/plotlykt-core/src/jsMain/ts/Plotly.d.ts @@ -0,0 +1,1599 @@ +// Type definitions for plotly.js 1.50 +// Project: https://plot.ly/javascript/, https://github.com/plotly/plotly.js +// Definitions by: Chris Gervang <https://github.com/chrisgervang> +// Martin Duparc <https://github.com/martinduparc> +// Frederik Aalund <https://github.com/frederikaalund> +// taoqf <https://github.com/taoqf> +// Dadstart <https://github.com/Dadstart> +// Jared Szechy <https://github.com/szechyjs> +// Drew Diamantoukos <https://github.com/MercifulCode> +// Sooraj Pudiyadath <https://github.com/soorajpudiyadath> +// Jon Freedman <https://github.com/jonfreedman> +// Megan Riel-Mehan <https://github.com/meganrm> +// Josh Miles <https://github.com/milesjos> +// Pramod Mathai <https://github.com/skippercool> +// Takafumi Yamaguchi <https://github.com/zeroyoichihachi> +// Michael Adams <https://github.com/mtadams007> +// Michael Arnett <https://github.com/marnett-git> +// Piotr Błażejewicz <https://github.com/peterblazejewicz> +// Brandon Mitchell <https://github.com/brammitch> +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +import * as _d3 from "getD3"; + +export as namespace Plotly; + +export interface StaticPlots { + resize(root: Root): void; +} + +export const Plots: StaticPlots; + +export interface Point { + x: number; + y: number; + z: number; +} + +export interface PlotScatterDataPoint { + curveNumber: number; + data: PlotData; + pointIndex: number; + pointNumber: number; + x: number; + xaxis: LayoutAxis; + y: number; + yaxis: LayoutAxis; +} + +export interface PlotDatum { + curveNumber: number; + data: PlotData; + pointIndex: number; + pointNumber: number; + x: Datum; + xaxis: LayoutAxis; + y: Datum; + yaxis: LayoutAxis; +} + +export interface PlotMouseEvent { + points: PlotDatum[]; + event: MouseEvent; +} + +export interface PlotCoordinate { + x: number; + y: number; + pointNumber: number; +} + +export interface SelectionRange { + x: number[]; + y: number[]; +} + +export type PlotSelectedData = Partial<PlotDatum>; + +export interface PlotSelectionEvent { + points: PlotDatum[]; + range?: SelectionRange; + lassoPoints?: SelectionRange; +} + +export type PlotRestyleEvent = [ + any, // update object -- attribute updated: new value + number[] // array of traces updated +]; + +export interface PlotAxis { + range: [number, number]; + autorange: boolean; +} + +export interface PlotScene { + center: Point; + eye: Point; + up: Point; +} + +export interface PlotRelayoutEvent { + xaxis: PlotAxis; + yaxis: PlotAxis; + scene: PlotScene; +} + +export interface ClickAnnotationEvent { + index: number; + annotation: Annotations; + fullAnnotation: Annotations; + event: MouseEvent; +} + +export interface FrameAnimationEvent { + name: string; + frame: Frame; + animation: { + frame: { + duration: number; + redraw: boolean; + }; + transition: Transition; + }; +} + +export interface LegendClickEvent { + event: MouseEvent; + node: PlotlyHTMLElement; + curveNumber: number; + expandedIndex: number; + data: Data[]; + layout: Partial<Layout>; + frames: Frame[]; + config: Partial<Config>; + fullData: Data[]; + fullLayout: Partial<Layout>; +} + +export interface SliderChangeEvent { + slider: Slider; + step: SliderStep; + interaction: boolean; + previousActive: number; +} + +export interface SliderStartEvent { + slider: Slider; +} + +export interface SliderEndEvent { + slider: Slider; + step: SliderStep; +} + +export interface BeforePlotEvent { + data: Data[]; + layout: Partial<Layout>; + config: Partial<Config>; +} + +export interface PlotlyHTMLElement extends HTMLElement { + on(event: 'plotly_click' | 'plotly_hover' | 'plotly_unhover', callback: (event: PlotMouseEvent) => void): void; + on(event: 'plotly_selecting' | 'plotly_selected', callback: (event: PlotSelectionEvent) => void): void; + on(event: 'plotly_restyle', callback: (data: PlotRestyleEvent) => void): void; + on(event: 'plotly_relayout', callback: (event: PlotRelayoutEvent) => void): void; + on(event: 'plotly_clickannotation', callback: (event: ClickAnnotationEvent) => void): void; + on(event: 'plotly_animatingframe', callback: (event: FrameAnimationEvent) => void): void; + on(event: 'plotly_legendclick' | 'plotly_legenddoubleclick', callback: (event: LegendClickEvent) => boolean): void; + on(event: 'plotly_sliderchange', callback: (event: SliderChangeEvent) => void): void; + on(event: 'plotly_sliderend', callback: (event: SliderEndEvent) => void): void; + on(event: 'plotly_sliderstart', callback: (event: SliderStartEvent) => void): void; + on(event: 'plotly_event', callback: (data: any) => void): void; + on(event: 'plotly_beforeplot', callback: (event: BeforePlotEvent) => boolean): void; + on(event: 'plotly_afterexport' | 'plotly_afterplot' | 'plotly_animated' | 'plotly_animationinterrupted' | 'plotly_autosize' | + 'plotly_beforeexport' | 'plotly_deselect' | 'plotly_doubleclick' | 'plotly_framework' | 'plotly_redraw' | + 'plotly_transitioning' | 'plotly_transitioninterrupted', callback: () => void): void; + removeAllListeners: (handler: string) => void; +} + +export interface ToImgopts { + format: 'jpeg' | 'png' | 'webp' | 'svg'; + width: number; + height: number; +} + +export interface DownloadImgopts { + format: 'jpeg' | 'png' | 'webp' | 'svg'; + width: number; + height: number; + filename: string; +} + +export interface PolarLayout { + domain: Partial<Domain>; + sector: number[]; + hole: number; + bgcolor: Color; + radialaxis: Partial<LayoutAxis>; + angularaxis: Partial<LayoutAxis>; + gridshape: 'circular' | 'linear'; + uirevision: string | number; +} + +export type Root = string | HTMLElement; + +export function newPlot(root: Root, data: Data[], layout?: Partial<Layout>, config?: Partial<Config>): Promise<PlotlyHTMLElement>; +export function plot(root: Root, data: Data[], layout?: Partial<Layout>, config?: Partial<Config>): Promise<PlotlyHTMLElement>; +export function relayout(root: Root, layout: Partial<Layout>): Promise<PlotlyHTMLElement>; +export function redraw(root: Root): Promise<PlotlyHTMLElement>; +export function purge(root: Root): void; +export const d3: typeof _d3; +export function restyle(root: Root, aobj: Data, traces?: number[] | number): Promise<PlotlyHTMLElement>; +export function update(root: Root, traceUpdate: Data, layoutUpdate: Partial<Layout>, traces?: number[] | number): Promise<PlotlyHTMLElement>; +export function addTraces(root: Root, traces: Data | Data[], newIndices?: number[] | number): Promise<PlotlyHTMLElement>; +export function deleteTraces(root: Root, indices: number[] | number): Promise<PlotlyHTMLElement>; +export function moveTraces(root: Root, currentIndices: number[] | number, newIndices?: number[] | number): Promise<PlotlyHTMLElement>; +export function extendTraces(root: Root, update: Data | Data[], indices: number | number[], maxPoints?: number): Promise<PlotlyHTMLElement>; +export function prependTraces(root: Root, update: Data | Data[], indices: number | number[]): Promise<PlotlyHTMLElement>; +export function toImage(root: Root, opts: ToImgopts): Promise<string>; +export function downloadImage(root: Root, opts: DownloadImgopts): Promise<string>; +export function react(root: Root, data: Data[], layout?: Partial<Layout>, config?: Partial<Config>): Promise<PlotlyHTMLElement>; +export function addFrames(root: Root, frames: Array<Partial<Frame>>): Promise<PlotlyHTMLElement>; +export function deleteFrames(root: Root, frames: number[]): Promise<PlotlyHTMLElement>; + +// Layout +export interface Layout { + title: string | Partial<{ + text: string; + font: Partial<Font>; + xref: 'container' | 'paper'; + yref: 'container' | 'paper'; + x: number; + y: number; + xanchor: 'auto' | 'left' | 'center' | 'right'; + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + pad: Partial<Padding> + }>; + titlefont: Partial<Font>; + autosize: boolean; + showlegend: boolean; + paper_bgcolor: Color; + plot_bgcolor: Color; + separators: string; + hidesources: boolean; + xaxis: Partial<LayoutAxis>; + xaxis2: Partial<LayoutAxis>; + xaxis3: Partial<LayoutAxis>; + xaxis4: Partial<LayoutAxis>; + xaxis5: Partial<LayoutAxis>; + xaxis6: Partial<LayoutAxis>; + xaxis7: Partial<LayoutAxis>; + xaxis8: Partial<LayoutAxis>; + xaxis9: Partial<LayoutAxis>; + yaxis: Partial<LayoutAxis>; + yaxis2: Partial<LayoutAxis>; + yaxis3: Partial<LayoutAxis>; + yaxis4: Partial<LayoutAxis>; + yaxis5: Partial<LayoutAxis>; + yaxis6: Partial<LayoutAxis>; + yaxis7: Partial<LayoutAxis>; + yaxis8: Partial<LayoutAxis>; + yaxis9: Partial<LayoutAxis>; + margin: Partial<Margin>; + height: number; + width: number; + hovermode: 'closest' | 'x' | 'y' | false; + hoverlabel: Partial<HoverLabel>; + calendar: Calendar; + 'xaxis.range': [Datum, Datum]; + 'xaxis.range[0]': Datum; + 'xaxis.range[1]': Datum; + 'yaxis.range': [Datum, Datum]; + 'yaxis.range[0]': Datum; + 'yaxis.range[1]': Datum; + 'yaxis.type': AxisType; + 'xaxis.type': AxisType; + 'xaxis.autorange': boolean; + 'yaxis.autorange': boolean; + 'xaxis.title': string; + 'yaxis.title': string; + ternary: {}; // TODO + geo: {}; // TODO + mapbox: {}; // TODO + radialaxis: Partial<Axis>; + angularaxis: {}; // TODO + dragmode: 'zoom' | 'pan' | 'select' | 'lasso' | 'orbit' | 'turntable' | false; + orientation: number; + annotations: Array<Partial<Annotations>>; + shapes: Array<Partial<Shape>>; + images: Array<Partial<Image>>; + updatemenus: {}; // TODO + sliders: Array<Partial<Slider>>; + legend: Partial<Legend>; + font: Partial<Font>; + scene: Partial<Scene>; + barmode: 'stack' | 'group' | 'overlay' | 'relative'; + barnorm: '' | 'fraction' | 'percent'; + bargap: 0 | 1; + bargroupgap: 0 | 1; + selectdirection: 'h' | 'v' | 'd' | 'any'; + hiddenlabels: string[]; + grid: Partial<{ + rows: number; + roworder: "top to bottom" | "bottom to top"; + columns: number; + subplots: string[]; + xaxes: string[]; + yaxes: string[]; + pattern: "independent" | "coupled"; + xgap: number; + ygap: number; + domain: Partial<{ + x: number[]; + y: number[]; + }>; + xside: "bottom" | "bottom plot" | "top plot" | "top"; + yside: "left" | "left plot" | "right plot" | "right"; + }>; + polar: Partial<PolarLayout>; + polar2: Partial<PolarLayout>; + polar3: Partial<PolarLayout>; + polar4: Partial<PolarLayout>; + polar5: Partial<PolarLayout>; + polar6: Partial<PolarLayout>; + polar7: Partial<PolarLayout>; + polar8: Partial<PolarLayout>; + polar9: Partial<PolarLayout>; + transition: Transition; +} + +export interface Legend extends Label { + traceorder: 'grouped' | 'normal' | 'reversed'; + x: number; + y: number; + borderwidth: number; + orientation: 'v' | 'h'; + tracegroupgap: number; + xanchor: 'auto' | 'left' | 'center' | 'right'; + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; +} + +export type AxisType = '-' | 'linear' | 'log' | 'date' | 'category'; + +export interface Axis { + visible: boolean; + color: Color; + title: string | Partial<DataTitle>; + titlefont: Partial<Font>; + type: AxisType; + autorange: true | false | 'reversed'; + rangemode: 'normal' | 'tozero' | 'nonnegative'; + range: any[]; + tickmode: 'auto' | 'linear' | 'array'; + nticks: number; + tick0: number | string; + dtick: number | string; + tickvals: any[]; + ticktext: string[]; + ticks: 'outside' | 'inside' | ''; + mirror: true | 'ticks' | false | 'all' | 'allticks'; + ticklen: number; + tickwidth: number; + tickcolor: Color; + showticklabels: boolean; + showspikes: boolean; + spikecolor: Color; + spikethickness: number; + categoryorder: 'trace' | 'category ascending' | 'category descending' | 'array' | 'total ascending' | 'total descending' | + 'min ascending' | 'min descending' | 'max ascending' | 'max descending' | 'sum ascending' | 'sum descending' | 'mean ascending' | + 'mean descending' | 'median ascending' | 'median descending'; + categoryarray: any[]; + tickfont: Partial<Font>; + tickangle: number; + tickprefix: string; + showtickprefix: 'all' | 'first' | 'last' | 'none'; + ticksuffix: string; + showticksuffix: 'all' | 'first' | 'last' | 'none'; + showexponent: 'all' | 'first' | 'last' | 'none'; + exponentformat: 'none' | 'e' | 'E' | 'power' | 'SI' | 'B'; + separatethousands: boolean; + tickformat: string; + hoverformat: string; + showline: boolean; + linecolor: Color; + linewidth: number; + showgrid: boolean; + gridcolor: Color; + gridwidth: number; + zeroline: boolean; + zerolinecolor: Color; + zerolinewidth: number; + calendar: Calendar; +} + +export type Calendar = 'gregorian' | 'chinese' | 'coptic' | 'discworld' | 'ethiopian' | 'hebrew' | 'islamic' | 'julian' | 'mayan' | + 'nanakshahi' | 'nepali' | 'persian' | 'jalali' | 'taiwan' | 'thai' | 'ummalqura'; + +export type AxisName = + | 'x' | 'x2' | 'x3' | 'x4' | 'x5' | 'x6' | 'x7' | 'x8' | 'x9' + | 'y' | 'y2' | 'y3' | 'y4' | 'y5' | 'y6' | 'y7' | 'y8' | 'y9'; + +export interface LayoutAxis extends Axis { + fixedrange: boolean; + scaleanchor: AxisName; + scaleratio: number; + constrain: 'range' | 'domain'; + constraintoward: 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom'; + spikedash: string; + spikemode: string; + anchor: 'free' | AxisName; + side: 'top' | 'bottom' | 'left' | 'right' | 'clockwise' | 'counterclockwise'; + overlaying: 'free' | AxisName; + layer: 'above traces' | 'below traces'; + domain: number[]; + position: number; + rangeslider: Partial<RangeSlider>; + rangeselector: Partial<RangeSelector>; + automargin: boolean; + autotick: boolean; + angle: any; +} + +export interface SceneAxis extends Axis { + spikesides: boolean; + showbackground: boolean; + backgroundcolor: Color; + showaxeslabels: boolean; +} + +export interface ShapeLine { + color: string; + width: number; + dash: Dash; +} + +export interface Shape { + visible: boolean; + layer: 'below' | 'above'; + type: 'rect' | 'circle' | 'line' | 'path'; + path: string; + // x-reference is assigned to the x-values + xref: 'x' | 'paper'; + xsizemode: "scaled" | "pixel"; + xanchor: number | string; + // y-reference is assigned to the plot paper [0,1] + yref: 'paper' | 'y'; + ysizemode: "scaled" | "pixel"; + yanchor: number | string; + x0: Datum; + y0: Datum; + x1: Datum; + y1: Datum; + fillcolor: string; + name: string; + templateitemname: string; + opacity: number; + line: Partial<ShapeLine>; +} + +export interface Margin { + t: number; + b: number; + l: number; + r: number; + pad: number; +} + +export type ModeBarDefaultButtons = + | 'lasso2d' + | 'select2d' + | 'sendDataToCloud' + | 'zoom2d' + | 'pan2d' + | 'zoomIn2d' + | 'zoomOut2d' + | 'autoScale2d' + | 'resetScale2d' + | 'hoverClosestCartesian' + | 'hoverCompareCartesian' + | 'zoom3d' + | 'pan3d' + | 'orbitRotation' + | 'tableRotation' + | 'resetCameraDefault3d' + | 'resetCameraLastSave3d' + | 'hoverClosest3d' + | 'zoomInGeo' + | 'zoomOutGeo' + | 'resetGeo' + | 'hoverClosestGeo' + | 'hoverClosestGl2d' + | 'hoverClosestPie' + | 'toggleHover' + | 'toImage' + | 'resetViews' + | 'toggleSpikelines'; + +export type ButtonClickEvent = (gd: PlotlyHTMLElement, ev: MouseEvent) => void; + +export interface Icon { + height?: number; + width?: number; + ascent?: number; + descent?: number; + name?: string; + path?: string; + svg?: string; + transform?: string; +} + +export interface ModeBarButton { + /** name / id of the buttons (for tracking) */ + name: string; + + /** + * text that appears while hovering over the button, + * enter null, false or '' for no hover text + */ + title: string; + + /** + * svg icon object associated with the button + * can be linked to Plotly.Icons to use the default plotly icons + */ + icon: string | Icon; + + /** icon positioning */ + gravity?: string; + + /** + * click handler associated with the button, a function of + * 'gd' (the main graph object) and + * 'ev' (the event object) + */ + click: ButtonClickEvent; + + /** + * attribute associated with button, + * use this with 'val' to keep track of the state + */ + attr?: string; + + /** initial 'attr' value, can be a function of gd */ + val?: any; + + /** is the button a toggle button? */ + toggle?: boolean; +} + +export interface GaugeLine { + color: Color; + width: number; +} +export interface Threshold { + line: Partial<GaugeLine>; + value: number; + thickness: number; +} + +export interface GaugeBar { + color: Color; + line: Partial<GaugeLine>; + thickness: number; +} +export interface Gauge { + shape: 'angular' | 'bullet'; + bar: Partial<GaugeBar>; + bgcolor: Color; + bordercolor: Color; + borderwidth: number; + axis: Partial<Axis>; + steps: Array<{range: number[], color: Color}>; + threshold: Partial<Threshold>; +} + +export interface Delta { + reference: number; + position: 'top' | 'bottom' | 'left' | 'right'; + relative: boolean; + valueformat: string; + increasing: { + symbol: string; + color: Color; + }; + decreasing: { + symbol: string; + color: Color; + }; +} + +export interface DataTitle { + text: string; + font: Partial<Font>; + position: "top left" | "top center" | "top right" | "middle center" | "bottom left" | "bottom center" | "bottom right"; +} + +export interface PlotNumber { + valueformat: string; + font: Partial<Font>; + prefix: string; + suffix: string; +} + +// Data + +export type Datum = string | number | Date | null; +export type TypedArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array; + +export interface ErrorOptions { + visible: boolean; + symmetric: boolean; + color: Color; + thickness: number; + width: number; + opacity: number; +} + +export type ErrorBar = Partial<ErrorOptions> & ({ + type: 'constant' | 'percent', + value: number, + valueminus?: number +} | { + type: 'data', + array: Datum[], + arrayminus?: Datum[] +}); + +export type Dash = 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot'; + +export type Data = Partial<PlotData>; +export type Color = string | number | Array<string | number | undefined | null> | Array<Array<string | number | undefined | null>>; +export type ColorScale = string | string[] | Array<[number, string]>; +export type DataTransform = Partial<Transform>; +export type ScatterData = PlotData; +// Bar Scatter +export interface PlotData { + type: 'bar' | 'box' | 'candlestick' | 'choropleth' | 'contour' | 'heatmap' | 'histogram' | 'indicator' | 'mesh3d' | + 'ohlc' | 'parcoords' | 'pie' | 'pointcloud' | 'scatter' | 'scatter3d' | 'scattergeo' | 'scattergl' | + 'scatterpolar' | 'scatterternary' | 'surface' | 'treemap' | 'waterfall' | 'funnel' | 'funnelarea'; + x: Datum[] | Datum[][] | TypedArray; + y: Datum[] | Datum[][] | TypedArray; + z: Datum[] | Datum[][] | Datum[][][] | TypedArray; + xy: Float32Array; + error_x: ErrorBar; + error_y: ErrorBar; + xaxis: string; + yaxis: string; + text: string | string[]; + line: Partial<ScatterLine>; + 'line.color': Color; + 'line.width': number; + 'line.dash': Dash; + 'line.shape': 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv'; + 'line.smoothing': number; + 'line.simplify': boolean; + marker: Partial<PlotMarker>; + 'marker.symbol': MarkerSymbol | MarkerSymbol[]; + 'marker.color': Color; + 'marker.colorscale': ColorScale | ColorScale[]; + 'marker.opacity': number | number[]; + 'marker.size': number | number[] | number[][]; + 'marker.maxdisplayed': number; + 'marker.sizeref': number; + 'marker.sizemax': number; + 'marker.sizemin': number; + 'marker.sizemode': 'diameter' | 'area'; + 'marker.showscale': boolean; + 'marker.line': Partial<ScatterMarkerLine>; + 'marker.line.color': Color; + 'marker.line.colorscale': ColorScale | ColorScale[]; + 'marker.colorbar': {}; // TODO + 'marker.pad.t': number; + 'marker.pad.b': number; + 'marker.pad.l': number; + 'marker.pad.r': number; + mode: 'lines' | 'markers' | 'text' | 'lines+markers' | 'text+markers' | 'text+lines' | 'text+lines+markers' | 'none' + | 'gauge' | 'number' | 'delta' | 'number+delta' | 'gauge+number' | 'gauge+number+delta' | 'gauge+delta'; + hoveron: 'points' | 'fills'; + hoverinfo: 'all' | 'name' | 'none' | 'skip' | 'text' | + 'x' | 'x+text' | 'x+name' | + 'x+y' | 'x+y+text' | 'x+y+name' | + 'x+y+z' | 'x+y+z+text' | 'x+y+z+name' | + 'y+name' | 'y+x' | 'y+text' | 'y+x+text' | 'y+x+name' | + 'y+z' | 'y+z+text' | 'y+z+name' | + 'y+x+z' | 'y+x+z+text' | 'y+x+z+name' | + 'z+x' | 'z+x+text' | 'z+x+name' | + 'z+y+x' | 'z+y+x+text' | 'z+y+x+name' | + 'z+x+y' | 'z+x+y+text' | 'z+x+y+name'; + hoverlabel: Partial<HoverLabel>; + hovertemplate: string | string[]; + hovertext: string | string[]; + textinfo: 'label' | 'label+text' | 'label+value' | 'label+percent' | 'label+text+value' + | 'label+text+percent' | 'label+value+percent' | 'text' | 'text+value' | 'text+percent' + | 'text+value+percent' | 'value' | 'value+percent' | 'percent' | 'none'; + textposition: "top left" | "top center" | "top right" | "middle left" + | "middle center" | "middle right" | "bottom left" | "bottom center" | "bottom right" | "inside" | "outside"; + textfont: Partial<Font>; + fill: 'none' | 'tozeroy' | 'tozerox' | 'tonexty' | 'tonextx' | 'toself' | 'tonext'; + fillcolor: string; + showlegend: boolean; + legendgroup: string; + parents: string[]; + name: string; + stackgroup: string; + connectgaps: boolean; + visible: boolean | 'legendonly'; + delta: Partial<Delta>; + gauge: Partial<Gauge>; + number: Partial<PlotNumber>; + transforms: DataTransform[]; + orientation: 'v' | 'h'; + width: number | number[]; + boxmean: boolean | 'sd'; + opacity: number; + showscale: boolean; + colorscale: ColorScale; + zsmooth: 'fast' | 'best' | false; + ygap: number; + xgap: number; + transpose: boolean; + autobinx: boolean; + xbins: { + start: number | string; + end: number | string; + size: number | string; + }; + value: number; + values: Datum[]; + labels: Datum[]; + direction: 'clockwise' | 'counterclockwise'; + hole: number; + rotation: number; + theta: Datum[]; + r: Datum[]; + customdata: Datum[]; + domain: Partial<{ + rows: number; + columns: number; + x: number[]; + y: number[]; + }>; + title: Partial<DataTitle>; +} + +/** + * These interfaces are based on attribute descriptions in + * https://github.com/plotly/plotly.js/tree/9d6144304308fc3007f0facf2535d38ea3e9b26c/src/transforms + */ + +export interface TransformStyle { + target: number | string | number[] | string[]; + value: Partial<PlotData>; +} + +export interface TransformAggregation { + target: string; + func?: 'count' | 'sum' | 'avg' | 'median' | 'mode' | 'rms' | 'stddev' | 'min' | 'max' | 'first' | 'last'; + funcmode?: 'sample' | 'population'; + enabled?: boolean; +} + +export interface Transform { + type: 'aggregate' | 'filter' | 'groupby' | 'sort'; + enabled: boolean; + target: number | string | number[] | string[]; + operation: string; + aggregations: TransformAggregation[]; + preservegaps: boolean; + groups: string | number[] | string[]; + nameformat: string; + styles: TransformStyle[]; + value: any; + order: 'ascending' | 'descending'; +} + +export interface ColorBar { + thicknessmode: 'fraction' | 'pixels'; + thickness: number; + lenmode: 'fraction' | 'pixels'; + len: number; + x: number; + xanchor: 'left' | 'center' | 'right'; + xpad: number; + y: number; + yanchor: 'top' | 'middle' | 'bottom'; + ypad: number; + outlinecolor: Color; + outlinewidth: number; + bordercolor: Color; + borderwidth: Color; + bgcolor: Color; + tickmode: 'auto' | 'linear' | 'array'; + nticks: number; + tick0: number | string; + dtick: number | string; + tickvals: Datum[] | Datum[][] | Datum[][][] | TypedArray; + ticktext: Datum[] | Datum[][] | Datum[][][] | TypedArray; + ticks: 'outside' | 'inside' | ''; + ticklen: number; + tickwidth: number; + tickcolor: Color; + showticklabels: boolean; + tickfont: Font; + tickangle: number; + tickformat: string; + tickformatstops: { + dtickrange: any[]; + value: string; + }; + tickprefix: string; + showtickprefix: 'all' | 'first' | 'last' | 'none'; + ticksuffix: string; + showticksuffix: 'all' | 'first' | 'last' | 'none'; + separatethousands: boolean; + exponentformat: 'none' | 'e' | 'E' | 'power' | 'SI' | 'B'; + showexponent: 'all' | 'first' | 'last' | 'none'; + title: string; + titlefont: Font; + titleside: 'right' | 'top' | 'bottom'; + tickvalssrc: any; + ticktextsrc: any; +} + +export type MarkerSymbol = string | number | Array<(string | number)>; + +/** + * Any combination of "x", "y", "z", "text", "name" joined with a "+" OR "all" or "none" or "skip". + * examples: "x", "y", "x+y", "x+y+z", "all" + * default: "all" + */ +export interface PlotMarker { + symbol: MarkerSymbol; + color: Color | Color[]; + colors: Color[]; + colorscale: ColorScale; + cauto: boolean; + cmax: number; + cmin: number; + autocolorscale: boolean; + reversescale: boolean; + opacity: number | number[]; + size: number | number[]; + maxdisplayed: number; + sizeref: number; + sizemax: number; + sizemin: number; + sizemode: 'diameter' | 'area'; + showscale: boolean; + line: Partial<ScatterMarkerLine>; + pad: Partial<Padding>; + width: number; + colorbar: Partial<ColorBar>; + gradient: { + type: 'radial' | 'horizontal' | 'vertical' | 'none', + color: Color, + typesrc: any, + colorsrc: any, + }; +} + +export type ScatterMarker = PlotMarker; + +export interface ScatterMarkerLine { + width: number | number[]; + color: Color; + colorscale: ColorScale; + cauto: boolean; + cmax: number; + cmin: number; + autocolorscale: boolean; + reversescale: boolean; +} + +export interface ScatterLine { + color: Color; + width: number; + dash: Dash; + shape: 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv'; + smoothing: number; + simplify: boolean; +} + +export interface Font { + /** + * HTML font family - the typeface that will be applied by the web browser. + * The web browser will only be able to apply a font if it is available on the system + * which it operates. Provide multiple font families, separated by commas, to indicate + * the preference in which to apply fonts if they aren't available on the system. + * The plotly service (at https://plot.ly or on-premise) generates images on a server, + * where only a select number of fonts are installed and supported. + * These include *Arial*, *Balto*, *Courier New*, *Droid Sans*, *Droid Serif*, + * *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, + * *PT Sans Narrow*, *Raleway*, *Times New Roman*. + */ + family: string; + size: number; + color: Color; +} + +export interface Edits { + annotationPosition: boolean; + annotationTail: boolean; + annotationText: boolean; + axisTitleText: boolean; + colorbarPosition: boolean; + colorbarTitleText: boolean; + legendPosition: boolean; + legendText: boolean; + shapePosition: boolean; + titleText: boolean; +} + +export interface Config { + /** override the defaults for the toImageButton */ + toImageButtonOptions: Partial<{ + filename: string; + scale: number; + format: 'png' | 'svg' | 'jpeg' | 'webp'; + height: number; + width: number; + }>; + + /** no interactivity, for export or image generation */ + staticPlot: boolean; + + /** we can edit titles, move annotations, etc */ + editable: boolean; + edits: Partial<Edits>; + + /** DO autosize once regardless of layout.autosize (use default width or height values otherwise) */ + autosizable: boolean; + + /** set the length of the undo/redo queue */ + queueLength: number; + + /** if we DO autosize, do we fill the container or the screen? */ + fillFrame: boolean; + + /** if we DO autosize, set the frame margins in percents of plot size */ + frameMargins: number; + + /** mousewheel or two-finger scroll zooms the plot */ + scrollZoom: boolean; + + /** double click interaction (false, 'reset', 'autosize' or 'reset+autosize') */ + doubleClick: 'reset+autosize' | 'reset' | 'autosize' | false; + + /** new users see some hints about interactivity */ + showTips: boolean; + + /** enable axis pan/zoom drag handles */ + showAxisDragHandles: boolean; + + /** enable direct range entry at the pan/zoom drag points (drag handles must be enabled above) */ + showAxisRangeEntryBoxes: boolean; + + /** link to open this plot in plotly */ + showLink: boolean; + + /** if we show a link, does it contain data or just link to a plotly file? */ + sendData: boolean; + + /** text appearing in the sendData link */ + linkText: string; + + /** false or function adding source(s) to linkText <text> */ + showSources: boolean; + + /** display the mode bar (true, false, or 'hover') */ + displayModeBar: 'hover' | boolean; + + /** remove mode bar button by name (see ./components/modebar/buttons.js for the list of names) */ + modeBarButtonsToRemove: ModeBarDefaultButtons[]; + + /** add mode bar button using config objects (see ./components/modebar/buttons.js for list of arguments) */ + modeBarButtonsToAdd: ModeBarDefaultButtons[] | ModeBarButton[]; + + /** + * fully custom mode bar buttons as nested array, where the outer + * arrays represents button groups, and the inner arrays have + * buttons config objects or names of default buttons + * (see ./components/modebar/buttons.js for more info) + */ + modeBarButtons: ModeBarDefaultButtons[][] | ModeBarButton[][] | false; + + /** add the plotly logo on the end of the mode bar */ + displaylogo: boolean; + + /** increase the pixel ratio for Gl plot images */ + plotGlPixelRatio: number; + + /** + * function to add the background color to a different container + * or 'opaque' to ensure there's white behind it + */ + setBackground: () => string | 'opaque' | 'transparent'; + + /** URL to topojson files used in geo charts */ + topojsonURL: string; + + /** + * Mapbox access token (required to plot mapbox trace types) + * If using an Mapbox Atlas server, set this option to '', + * so that plotly.js won't attempt to authenticate to the public Mapbox server. + */ + mapboxAccessToken: string; + + /** + * Turn all console logging on or off (errors will be thrown) + * This should ONLY be set via Plotly.setPlotConfig + */ + logging: boolean | 0 | 1 | 2; + + /** Set global transform to be applied to all traces with no specification needed */ + globalTransforms: any[]; + + /** Which localization should we use? Should be a string like 'en' or 'en-US' */ + locale: string; + + /** Make the chart responsive to window size */ + responsive: boolean; +} + +// Components + +export interface RangeSlider { + visible: boolean; + thickness: number; + range: [Datum, Datum]; + borderwidth: number; + bordercolor: string; + bgcolor: string; +} + +export interface RangeSelectorButton { + step: 'second' | 'minute' | 'hour' | 'day' | 'month' | 'year' | 'all'; + stepmode: 'backward' | 'todate'; + count: number; + label: string; +} + +export interface RangeSelector extends Label { + buttons: Array<Partial<RangeSelectorButton>>; + visible: boolean; + x: number; + xanchor: 'auto' | 'left' | 'center' | 'right'; + y: number; + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + activecolor: string; + borderwidth: number; +} + +export interface Camera { + up: Partial<Point>; + center: Partial<Point>; + eye: Partial<Point>; +} + +export interface Label { + /** Sets the background color of all hover labels on graph. */ + bgcolor: string; + + /** Sets the border color of all hover labels on graph. */ + bordercolor: string; + + /** Sets the default hover label font used by all traces on the graph. */ + font: Partial<Font>; +} + +export interface HoverLabel extends Label { + /** Sets the horizontal alignment of the text content within hover label box. */ + align: "left" | "right" | "auto"; + + /** + * Sets the default length (in number of characters) (default 15) of the trace name + * in the hover labels for all traces. + * -1 shows the whole name regardless of length. + */ + namelength: number; +} + +export interface Annotations extends Label { + /** Determines whether or not this annotation is visible. */ + visible: boolean; + + /** + * Sets the text associated with this annotation. + * Plotly uses a subset of HTML tags to do things like + * newline (<br>), bold (<b></b>), italics (<i></i>), + * hyperlinks (<a href='...'></a>). Tags <em>, <sup>, <sub> + * <span> are also supported. + */ + text: string; + + /** Sets the angle at which the `text` is drawn with respect to the horizontal. */ + textangle: string; + + /** + * Sets an explicit width for the text box. null (default) lets the + * text set the box width. Wider text will be clipped. + * There is no automatic wrapping; use <br> to start a new line. + */ + width: number; + + /** + * Sets an explicit height for the text box. null (default) lets the + * text set the box height. Taller text will be clipped. + */ + height: number; + + /** Sets the opacity of the annotation (text + arrow). */ + opacity: number; + + /** + * Sets the horizontal alignment of the `text` within the box. + * Has an effect only if `text` spans more two or more lines + * (i.e. `text` contains one or more <br> HTML tags) or if an + * explicit width is set to override the text width. + */ + align: 'left' | 'center' | 'right'; + + /** + * Sets the vertical alignment of the `text` within the box. + * Has an effect only if an explicit height is set to override the text height. + */ + valign: 'top' | 'middle' | 'bottom'; + + /** Sets the padding (in px) between the `text` and the enclosing border. */ + borderpad: number; + + /** Sets the width (in px) of the border enclosing the annotation `text`. */ + borderwidth: number; + + /** + * Determines whether or not the annotation is drawn with an arrow. + * If *true*, `text` is placed near the arrow's tail. + * If *false*, `text` lines up with the `x` and `y` provided. + */ + showarrow: boolean; + + /** Sets the color of the annotation arrow. */ + arrowcolor: string; + + /** Sets the end annotation arrow head style. */ + arrowhead: number; + + /** Sets the start annotation arrow head style. */ + startarrowhead: number; + + /** Sets the annotation arrow head position. */ + arrowside: 'end' | 'start'; + + /** + * Sets the size of the end annotation arrow head, relative to `arrowwidth`. + * A value of 1 (default) gives a head about 3x as wide as the line. + */ + arrowsize: number; + + /** + * Sets the size of the start annotation arrow head, relative to `arrowwidth`. + * A value of 1 (default) gives a head about 3x as wide as the line. + */ + startarrowsize: number; + + /** Sets the width (in px) of annotation arrow line. */ + arrowwidth: number; + + /** + * Sets a distance, in pixels, to move the end arrowhead away from the + * position it is pointing at, for example to point at the edge of + * a marker independent of zoom. Note that this shortens the arrow + * from the `ax` / `ay` vector, in contrast to `xshift` / `yshift` + * which moves everything by this amount. + */ + standoff: number; + + /** + * Sets a distance, in pixels, to move the start arrowhead away from the + * position it is pointing at, for example to point at the edge of + * a marker independent of zoom. Note that this shortens the arrow + * from the `ax` / `ay` vector, in contrast to `xshift` / `yshift` + * which moves everything by this amount. + */ + startstandoff: number; + + /** + * Sets the x component of the arrow tail about the arrow head. + * If `axref` is `pixel`, a positive (negative) + * component corresponds to an arrow pointing + * from right to left (left to right). + * If `axref` is an axis, this is an absolute value on that axis, + * like `x`, NOT a relative value. + */ + ax: number; + + /** + * Sets the y component of the arrow tail about the arrow head. + * If `ayref` is `pixel`, a positive (negative) + * component corresponds to an arrow pointing + * from bottom to top (top to bottom). + * If `ayref` is an axis, this is an absolute value on that axis, + * like `y`, NOT a relative value. + */ + ay: number; + + /** + * Indicates in what terms the tail of the annotation (ax,ay) + * is specified. If `pixel`, `ax` is a relative offset in pixels + * from `x`. If set to an x axis id (e.g. *x* or *x2*), `ax` is + * specified in the same terms as that axis. This is useful + * for trendline annotations which should continue to indicate + * the correct trend when zoomed. + */ + axref: 'pixel'; + + /** + * Indicates in what terms the tail of the annotation (ax,ay) + * is specified. If `pixel`, `ay` is a relative offset in pixels + * from `y`. If set to a y axis id (e.g. *y* or *y2*), `ay` is + * specified in the same terms as that axis. This is useful + * for trendline annotations which should continue to indicate + * the correct trend when zoomed. + */ + ayref: 'pixel'; + + /** + * Sets the annotation's x coordinate axis. + * If set to an x axis id (e.g. *x* or *x2*), the `x` position refers to an x coordinate + * If set to *paper*, the `x` position refers to the distance from + * the left side of the plotting area in normalized coordinates + * where 0 (1) corresponds to the left (right) side. + */ + xref: 'paper' | 'x'; + + /** + * Sets the annotation's x position. + * If the axis `type` is *log*, then you must take the log of your desired range. + * If the axis `type` is *date*, it should be date strings, like date data, + * though Date objects and unix milliseconds will be accepted and converted to strings. + * If the axis `type` is *category*, it should be numbers, using the scale where each + * category is assigned a serial number from zero in the order it appears. + */ + x: number | string; + + /** + * Sets the text box's horizontal position anchor + * This anchor binds the `x` position to the *left*, *center* or *right* of the annotation. + * For example, if `x` is set to 1, `xref` to *paper* and `xanchor` to *right* then the + * right-most portion of the annotation lines up with the right-most edge of the plotting area. + * If *auto*, the anchor is equivalent to *center* for data-referenced annotations or if there + * is an arrow, whereas for paper-referenced with no arrow, the anchor picked corresponds to the closest side. + */ + xanchor: 'auto' | 'left' | 'center' | 'right'; + + /** + * Shifts the position of the whole annotation and arrow to the + * right (positive) or left (negative) by this many pixels. + */ + xshift: number; + + /** + * Sets the annotation's y coordinate axis. + * If set to an y axis id (e.g. *y* or *y2*), the `y` position refers to an y coordinate + * If set to *paper*, the `y` position refers to the distance from + * the bottom of the plotting area in normalized coordinates + * where 0 (1) corresponds to the bottom (top). + */ + yref: 'paper' | 'y'; + + /** + * Sets the annotation's y position. + * If the axis `type` is *log*, then you must take the log of your desired range. + * If the axis `type` is *date*, it should be date strings, like date data, + * though Date objects and unix milliseconds will be accepted and converted to strings. + * If the axis `type` is *category*, it should be numbers, using the scale where each + * category is assigned a serial number from zero in the order it appears. + */ + y: number | string; + + /** + * Sets the text box's vertical position anchor + * This anchor binds the `y` position to the *top*, *middle* or *bottom* of the annotation. + * For example, if `y` is set to 1, `yref` to *paper* and `yanchor` to *top* then the + * top-most portion of the annotation lines up with the top-most edge of the plotting area. + * If *auto*, the anchor is equivalent to *middle* for data-referenced annotations or if + * there is an arrow, whereas for paper-referenced with no arrow, the anchor picked + * corresponds to the closest side. + */ + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + + /** + * Shifts the position of the whole annotation and arrow up + * (positive) or down (negative) by this many pixels. + */ + yshift: number; + + /** + * Makes this annotation respond to clicks on the plot. + * If you click a data point that exactly matches the `x` and `y` values of this annotation, + * and it is hidden (visible: false), it will appear. In *onoff* mode, you must click the same + * point again to make it disappear, so if you click multiple points, you can show multiple + * annotations. In *onout* mode, a click anywhere else in the plot (on another data point or not) + * will hide this annotation. If you need to show/hide this annotation in response to different + * `x` or `y` values, you can set `xclick` and/or `yclick`. This is useful for example to label + * the side of a bar. To label markers though, `standoff` is preferred over `xclick` and `yclick`. + */ + clicktoshow: false | 'onoff' | 'onout'; + + /** + * Toggle this annotation when clicking a data point whose `x` value + * is `xclick` rather than the annotation's `x` value. + */ + xclick: any; + + /** + * Toggle this annotation when clicking a data point whose `y` value + * is `yclick` rather than the annotation's `y` value. + */ + yclick: any; + + /** + * Sets text to appear when hovering over this annotation. + * If omitted or blank, no hover label will appear. + */ + hovertext: string; + + hoverlabel: Partial<HoverLabel>; + + /** + * Determines whether the annotation text box captures mouse move and click events, + * or allows those events to pass through to data points in the plot that may be + * behind the annotation. By default `captureevents` is *false* unless `hovertext` + * is provided. If you use the event `plotly_clickannotation` without `hovertext` + * you must explicitly enable `captureevents`. + */ + captureevents: boolean; +} + +export interface Image { + visible: boolean; + source: string; + layer: 'above' | 'below'; + sizex: number; + sizey: number; + sizing: 'fill' | 'contain' | 'stretch'; + opacity: number; + x: number | string; + y: number | string; + xanchor: 'left' | 'center' | 'right'; + yanchor: 'top' | 'middle' | 'bottom'; + xref: 'paper' | 'x'; + yref: 'paper' | 'y'; +} + +export interface Scene { + bgcolor: string; + camera: Partial<Camera>; + domain: Partial<Domain>; + aspectmode: 'auto' | 'cube' | 'data' | 'manual'; + aspectratio: Partial<Point>; + xaxis: Partial<SceneAxis>; + yaxis: Partial<SceneAxis>; + zaxis: Partial<SceneAxis>; + dragmode: 'orbit' | 'turntable' | 'zoom' | 'pan' | false; + hovermode: 'closest' | false; + annotations: Partial<Annotations> | Array<Partial<Annotations>>; + captureevents: boolean; +} + +export interface Domain { + x: number[]; + y: number[]; + row: number; + column: number; +} + +export interface Frame { + /** + * An identifier that specifies the group to which the frame belongs, + * used by animate to select a subset of frames. + */ + group: string; + /** + * A label by which to identify the frame + */ + name: string; + /** + * A list of trace indices that identify the respective traces in the + * data attribute + */ + traces: number[]; + /** + * The name of the frame into which this frame's properties are merged + * before applying. This is used to unify properties and avoid needing + * to specify the same values for the same properties in multiple frames. + */ + baseframe: string; + /** + * A list of traces this frame modifies. The format is identical to the + * normal trace definition. + */ + data: Data[]; + /** + * Layout properties which this frame modifies. The format is identical + * to the normal layout definition. + */ + layout: Partial<Layout>; +} + +export interface Transition { + /** + * Sets the duration of the slider transition + */ + duration: number; + /** + * Sets the easing function of the slider transition + */ + easing: 'linear' | 'quad' | 'cubic' | 'sin' | 'exp' | 'circle' | 'elastic' | 'back' | 'bounce' | 'linear-in' | + 'quad-in' | 'cubic-in' | 'sin-in' | 'exp-in' | 'circle-in' | 'elastic-in' | 'back-in' | 'bounce-in' | + 'linear-out' | 'quad-out' | 'cubic-out' | 'sin-out' | 'exp-out' | 'circle-out' | 'elastic-out' | 'back-out' | + 'bounce-out' | 'linear-in-out' | 'quad-in-out' | 'cubic-in-out' | 'sin-in-out' | 'exp-in-out' | + 'circle-in-out' | 'elastic-in-out' | 'back-in-out' | 'bounce-in-out'; + /** + * Determines whether the figure's layout or traces smoothly transitions during updates that make both traces + * and layout change. Default is "layout first". + */ + ordering?: 'layout first' | 'traces first'; +} + +export interface SliderStep { + /** + * Determines whether or not this step is included in the slider. + */ + visible: boolean; + /** + * Sets the Plotly method to be called when the slider value is changed. + * If the `skip` method is used, the API slider will function as normal + * but will perform no API calls and will not bind automatically to state + * updates. This may be used to create a component interface and attach to + * slider events manually via JavaScript. + */ + method: 'animate' | 'relayout' | 'restyle' | 'skip' | 'update'; + /** + * Sets the arguments values to be passed to the Plotly + * method set in `method` on slide. + */ + args: any[]; + /** + * Sets the text label to appear on the slider + */ + label: string; + /** + * Sets the value of the slider step, used to refer to the step programatically. + * Defaults to the slider label if not provided. + */ + value: string; + /** + * When true, the API method is executed. When false, all other behaviors are the same + * and command execution is skipped. This may be useful when hooking into, for example, + * the `plotly_sliderchange` method and executing the API command manually without losing + * the benefit of the slider automatically binding to the state of the plot through the + * specification of `method` and `args`. + */ + execute: boolean; +} + +export interface Padding { + /** + * The amount of padding (in px) along the top of the component. + */ + t: number; + /** + * The amount of padding (in px) on the right side of the component. + */ + r: number; + /** + * The amount of padding (in px) along the bottom of the component. + */ + b: number; + /** + * The amount of padding (in px) on the left side of the component. + */ + l: number; + editType: 'arraydraw'; +} + +export interface Slider { + /** + * Determines whether or not the slider is visible. + */ + visible: boolean; + /** + * Determines which button (by index starting from 0) is + * considered active. + */ + active: number; + steps: Array<Partial<SliderStep>>; + /** + * Determines whether this slider length + * is set in units of plot *fraction* or in *pixels. + * Use `len` to set the value. + */ + lenmode: 'fraction' | 'pixels'; + /** + * Sets the length of the slider + * This measure excludes the padding of both ends. + * That is, the slider's length is this length minus the + * padding on both ends. + */ + len: number; + /** + * Sets the x position (in normalized coordinates) of the slider. + */ + x: number; + /** + * Sets the y position (in normalized coordinates) of the slider. + */ + y: number; + /** + * Set the padding of the slider component along each side. + */ + pad: Partial<Padding>; + /** + * Sets the slider's horizontal position anchor. + * This anchor binds the `x` position to the *left*, *center* + * or *right* of the range selector. + */ + xanchor: 'auto' | 'left' | 'center' | 'right'; + /** + * Sets the slider's vertical position anchor + * This anchor binds the `y` position to the *top*, *middle* + * or *bottom* of the range selector. + */ + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + transition: Transition; + currentvalue: { + /** + * Shows the currently-selected value above the slider. + */ + visible: boolean; + /** + * The alignment of the value readout relative to the length of the slider. + */ + xanchor: 'left' | 'center' | 'right'; + /** + * The amount of space, in pixels, between the current value label + * and the slider. + */ + offset: number; + /** + * When currentvalue.visible is true, this sets the prefix of the label. + */ + prefix: string; + /** + * When currentvalue.visible is true, this sets the suffix of the label. + */ + suffix: string; + /** + * Sets the font of the current value label text. + */ + font: Partial<Font>; + }; + /** + * Sets the font of the slider step labels. + */ + font: Font; + /** + * Sets the background color of the slider grip + * while dragging. + */ + activebgcolor: Color; + /** + * Sets the background color of the slider. + */ + bgcolor: Color; + /** + * Sets the color of the border enclosing the slider. + */ + bordercolor: Color; + /** + * Sets the width (in px) of the border enclosing the slider. + */ + borderwidth: number; + /** + * Sets the length in pixels of step tick marks + */ + ticklen: number; + /** + * Sets the color of the border enclosing the slider. + */ + tickcolor: Color; + /** + * Sets the tick width (in px). + */ + tickwidth: number; + /** + * Sets the length in pixels of minor step tick marks + */ + minorticklen: number; +} diff --git a/plotly/plotlykt-core/src/jsMain/ts/Plotly.ts.kt b/plotly/plotlykt-core/src/jsMain/ts/Plotly.ts.kt new file mode 100644 index 00000000..78937749 --- /dev/null +++ b/plotly/plotlykt-core/src/jsMain/ts/Plotly.ts.kt @@ -0,0 +1,3109 @@ +@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", "EXTERNAL_DELEGATION") + +import kotlin.js.* +import kotlin.js.Json +import org.khronos.webgl.* +import org.w3c.dom.* +import org.w3c.dom.events.* +import org.w3c.dom.parsing.* +import org.w3c.dom.svg.* +import org.w3c.dom.url.* +import org.w3c.fetch.* +import org.w3c.files.* +import org.w3c.notifications.* +import org.w3c.performance.* +import org.w3c.workers.* +import org.w3c.xhr.* + +external interface StaticPlots { + fun resize(root: String) + fun resize(root: HTMLElement) +} + +external var Plots: StaticPlots + +external interface Point { + var x: Number + var y: Number + var z: Number +} + +external interface PointPartial { + var x: Number? + get() = definedExternally + set(value) = definedExternally + var y: Number? + get() = definedExternally + set(value) = definedExternally + var z: Number? + get() = definedExternally + set(value) = definedExternally +} + +external interface PlotScatterDataPoint { + var curveNumber: Number + var data: PlotData + var pointIndex: Number + var pointNumber: Number + var x: Number + var xaxis: LayoutAxis + var y: Number + var yaxis: LayoutAxis +} + +external interface PlotDatum { + var curveNumber: Number + var data: PlotData + var pointIndex: Number + var pointNumber: Number + var x: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var xaxis: LayoutAxis + var y: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var yaxis: LayoutAxis +} + +external interface PlotDatumPartial { + var curveNumber: Number? + get() = definedExternally + set(value) = definedExternally + var data: PlotData? + get() = definedExternally + set(value) = definedExternally + var pointIndex: Number? + get() = definedExternally + set(value) = definedExternally + var pointNumber: Number? + get() = definedExternally + set(value) = definedExternally + var x: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var xaxis: LayoutAxis? + get() = definedExternally + set(value) = definedExternally + var y: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var yaxis: LayoutAxis? + get() = definedExternally + set(value) = definedExternally +} + +external interface PlotMouseEvent { + var points: Array<PlotDatum> + var event: MouseEvent +} + +external interface PlotCoordinate { + var x: Number + var y: Number + var pointNumber: Number +} + +external interface SelectionRange { + var x: Array<Number> + var y: Array<Number> +} + +typealias PlotSelectedData = PlotDatumPartial + +external interface PlotSelectionEvent { + var points: Array<PlotDatum> + var range: SelectionRange? + get() = definedExternally + set(value) = definedExternally + var lassoPoints: SelectionRange? + get() = definedExternally + set(value) = definedExternally +} + +external interface PlotAxis { + var range: dynamic /* JsTuple<Number, Number> */ + get() = definedExternally + set(value) = definedExternally + var autorange: Boolean +} + +external interface PlotScene { + var center: Point + var eye: Point + var up: Point +} + +external interface PlotRelayoutEvent { + var xaxis: PlotAxis + var yaxis: PlotAxis + var scene: PlotScene +} + +external interface ClickAnnotationEvent { + var index: Number + var annotation: Annotations + var fullAnnotation: Annotations + var event: MouseEvent +} + +external interface `T$0` { + var duration: Number + var redraw: Boolean +} + +external interface `T$1` { + var frame: `T$0` + var transition: Transition +} + +external interface FrameAnimationEvent { + var name: String + var frame: Frame + var animation: `T$1` +} + +external interface LegendClickEvent { + var event: MouseEvent + var node: PlotlyHTMLElement + var curveNumber: Number + var expandedIndex: Number + var data: Array<Data> + var layout: LayoutPartial + var frames: Array<Frame> + var config: ConfigPartial + var fullData: Array<Data> + var fullLayout: LayoutPartial +} + +external interface SliderChangeEvent { + var slider: Slider + var step: SliderStep + var interaction: Boolean + var previousActive: Number +} + +external interface SliderStartEvent { + var slider: Slider +} + +external interface SliderEndEvent { + var slider: Slider + var step: SliderStep +} + +external interface BeforePlotEvent { + var data: Array<Data> + var layout: LayoutPartial + var config: ConfigPartial +} + +external interface PlotlyHTMLElement : HTMLElement { + fun on(event: String, callback: (event: PlotMouseEvent) -> Unit) + fun on(event: String, callback: (event: PlotSelectionEvent) -> Unit) + fun on(event: String /* 'plotly_restyle' */, callback: (data: dynamic /* JsTuple<Any, Array<Number>> */) -> Unit) + fun on(event: String /* 'plotly_relayout' */, callback: (event: PlotRelayoutEvent) -> Unit) + fun on(event: String /* 'plotly_clickannotation' */, callback: (event: ClickAnnotationEvent) -> Unit) + fun on(event: String /* 'plotly_animatingframe' */, callback: (event: FrameAnimationEvent) -> Unit) + fun on(event: String, callback: (event: LegendClickEvent) -> Boolean) + fun on(event: String /* 'plotly_sliderchange' */, callback: (event: SliderChangeEvent) -> Unit) + fun on(event: String /* 'plotly_sliderend' */, callback: (event: SliderEndEvent) -> Unit) + fun on(event: String /* 'plotly_sliderstart' */, callback: (event: SliderStartEvent) -> Unit) + fun on(event: String /* 'plotly_event' */, callback: (data: Any) -> Unit) + fun on(event: String /* 'plotly_beforeplot' */, callback: (event: BeforePlotEvent) -> Boolean) + fun on(event: String, callback: () -> Unit) + var removeAllListeners: (handler: String) -> Unit +} + +external interface ToImgopts { + var format: String /* 'jpeg' | 'png' | 'webp' | 'svg' */ + var width: Number + var height: Number +} + +external interface DownloadImgopts { + var format: String /* 'jpeg' | 'png' | 'webp' | 'svg' */ + var width: Number + var height: Number + var filename: String +} + +external interface PolarLayout { + var domain: DomainPartial + var sector: Array<Number> + var hole: Number + var bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var radialaxis: LayoutAxisPartial + var angularaxis: LayoutAxisPartial + var gridshape: String /* 'circular' | 'linear' */ + var uirevision: dynamic /* String | Number */ + get() = definedExternally + set(value) = definedExternally +} + +external interface PolarLayoutPartial { + var domain: Any? + get() = definedExternally + set(value) = definedExternally + var sector: Array<Number>? + get() = definedExternally + set(value) = definedExternally + var hole: Number? + get() = definedExternally + set(value) = definedExternally + var bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var radialaxis: Any? + get() = definedExternally + set(value) = definedExternally + var angularaxis: Any? + get() = definedExternally + set(value) = definedExternally + var gridshape: String /* 'circular' | 'linear' */ + var uirevision: dynamic /* String | Number */ + get() = definedExternally + set(value) = definedExternally +} + +external fun newPlot(root: String, data: Array<Data>, layout: LayoutPartial? = definedExternally, config: ConfigPartial? = definedExternally): Promise<PlotlyHTMLElement> + +external fun newPlot(root: HTMLElement, data: Array<Data>, layout: LayoutPartial? = definedExternally, config: ConfigPartial? = definedExternally): Promise<PlotlyHTMLElement> + +external fun plot(root: String, data: Array<Data>, layout: LayoutPartial? = definedExternally, config: ConfigPartial? = definedExternally): Promise<PlotlyHTMLElement> + +external fun plot(root: HTMLElement, data: Array<Data>, layout: LayoutPartial? = definedExternally, config: ConfigPartial? = definedExternally): Promise<PlotlyHTMLElement> + +external fun relayout(root: String, layout: LayoutPartial): Promise<PlotlyHTMLElement> + +external fun relayout(root: HTMLElement, layout: LayoutPartial): Promise<PlotlyHTMLElement> + +external fun redraw(root: String): Promise<PlotlyHTMLElement> + +external fun redraw(root: HTMLElement): Promise<PlotlyHTMLElement> + +external fun purge(root: String) + +external fun purge(root: HTMLElement) + +external var d3: Any + +external fun restyle(root: String, aobj: Data, traces: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun restyle(root: String, aobj: Data, traces: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun restyle(root: HTMLElement, aobj: Data, traces: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun restyle(root: HTMLElement, aobj: Data, traces: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun update(root: String, traceUpdate: Data, layoutUpdate: LayoutPartial, traces: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun update(root: String, traceUpdate: Data, layoutUpdate: LayoutPartial, traces: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun update(root: HTMLElement, traceUpdate: Data, layoutUpdate: LayoutPartial, traces: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun update(root: HTMLElement, traceUpdate: Data, layoutUpdate: LayoutPartial, traces: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun addTraces(root: String, traces: Data, newIndices: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun addTraces(root: String, traces: Data, newIndices: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun addTraces(root: String, traces: Array<Data>, newIndices: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun addTraces(root: String, traces: Array<Data>, newIndices: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun addTraces(root: HTMLElement, traces: Data, newIndices: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun addTraces(root: HTMLElement, traces: Data, newIndices: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun addTraces(root: HTMLElement, traces: Array<Data>, newIndices: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun addTraces(root: HTMLElement, traces: Array<Data>, newIndices: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun deleteTraces(root: String, indices: Array<Number>): Promise<PlotlyHTMLElement> + +external fun deleteTraces(root: String, indices: Number): Promise<PlotlyHTMLElement> + +external fun deleteTraces(root: HTMLElement, indices: Array<Number>): Promise<PlotlyHTMLElement> + +external fun deleteTraces(root: HTMLElement, indices: Number): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: String, currentIndices: Array<Number>, newIndices: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: String, currentIndices: Array<Number>, newIndices: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: String, currentIndices: Number, newIndices: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: String, currentIndices: Number, newIndices: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: HTMLElement, currentIndices: Array<Number>, newIndices: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: HTMLElement, currentIndices: Array<Number>, newIndices: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: HTMLElement, currentIndices: Number, newIndices: Array<Number>? = definedExternally): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: HTMLElement, currentIndices: Number, newIndices: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun extendTraces(root: String, update: Data, indices: Number, maxPoints: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun extendTraces(root: String, update: Data, indices: Array<Number>, maxPoints: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun extendTraces(root: String, update: Array<Data>, indices: Number, maxPoints: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun extendTraces(root: String, update: Array<Data>, indices: Array<Number>, maxPoints: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun extendTraces(root: HTMLElement, update: Data, indices: Number, maxPoints: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun extendTraces(root: HTMLElement, update: Data, indices: Array<Number>, maxPoints: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun extendTraces(root: HTMLElement, update: Array<Data>, indices: Number, maxPoints: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun extendTraces(root: HTMLElement, update: Array<Data>, indices: Array<Number>, maxPoints: Number? = definedExternally): Promise<PlotlyHTMLElement> + +external fun prependTraces(root: String, update: Data, indices: Number): Promise<PlotlyHTMLElement> + +external fun prependTraces(root: String, update: Data, indices: Array<Number>): Promise<PlotlyHTMLElement> + +external fun prependTraces(root: String, update: Array<Data>, indices: Number): Promise<PlotlyHTMLElement> + +external fun prependTraces(root: String, update: Array<Data>, indices: Array<Number>): Promise<PlotlyHTMLElement> + +external fun prependTraces(root: HTMLElement, update: Data, indices: Number): Promise<PlotlyHTMLElement> + +external fun prependTraces(root: HTMLElement, update: Data, indices: Array<Number>): Promise<PlotlyHTMLElement> + +external fun prependTraces(root: HTMLElement, update: Array<Data>, indices: Number): Promise<PlotlyHTMLElement> + +external fun prependTraces(root: HTMLElement, update: Array<Data>, indices: Array<Number>): Promise<PlotlyHTMLElement> + +external fun toImage(root: String, opts: ToImgopts): Promise<String> + +external fun toImage(root: HTMLElement, opts: ToImgopts): Promise<String> + +external fun downloadImage(root: String, opts: DownloadImgopts): Promise<String> + +external fun downloadImage(root: HTMLElement, opts: DownloadImgopts): Promise<String> + +external fun react(root: String, data: Array<Data>, layout: LayoutPartial? = definedExternally, config: ConfigPartial? = definedExternally): Promise<PlotlyHTMLElement> + +external fun react(root: HTMLElement, data: Array<Data>, layout: LayoutPartial? = definedExternally, config: ConfigPartial? = definedExternally): Promise<PlotlyHTMLElement> + +external fun addFrames(root: String, frames: Array<FramePartial>): Promise<PlotlyHTMLElement> + +external fun addFrames(root: HTMLElement, frames: Array<FramePartial>): Promise<PlotlyHTMLElement> + +external fun deleteFrames(root: String, frames: Array<Number>): Promise<PlotlyHTMLElement> + +external fun deleteFrames(root: HTMLElement, frames: Array<Number>): Promise<PlotlyHTMLElement> + +external interface `T$2` { + var text: String? + get() = definedExternally + set(value) = definedExternally + var font: FontPartial? + get() = definedExternally + set(value) = definedExternally + var xref: String /* 'container' | 'paper' */ + var yref: String /* 'container' | 'paper' */ + var x: Number? + get() = definedExternally + set(value) = definedExternally + var y: Number? + get() = definedExternally + set(value) = definedExternally + var xanchor: String /* 'auto' | 'left' | 'center' | 'right' */ + var yanchor: String /* 'auto' | 'top' | 'middle' | 'bottom' */ + var pad: PaddingPartial? + get() = definedExternally + set(value) = definedExternally +} + +external interface `T$3` { + var x: Array<Number>? + get() = definedExternally + set(value) = definedExternally + var y: Array<Number>? + get() = definedExternally + set(value) = definedExternally +} + +external interface `T$4` { + var rows: Number? + get() = definedExternally + set(value) = definedExternally + var roworder: String /* "top to bottom" | "bottom to top" */ + var columns: Number? + get() = definedExternally + set(value) = definedExternally + var subplots: Array<String>? + get() = definedExternally + set(value) = definedExternally + var xaxes: Array<String>? + get() = definedExternally + set(value) = definedExternally + var yaxes: Array<String>? + get() = definedExternally + set(value) = definedExternally + var pattern: String /* "independent" | "coupled" */ + var xgap: Number? + get() = definedExternally + set(value) = definedExternally + var ygap: Number? + get() = definedExternally + set(value) = definedExternally + var domain: `T$3`? + get() = definedExternally + set(value) = definedExternally + var xside: String /* "bottom" | "bottom plot" | "top plot" | "top" */ + var yside: String /* "left" | "left plot" | "right plot" | "right" */ +} + +external interface Layout { + var title: dynamic /* String | `T$2` */ + get() = definedExternally + set(value) = definedExternally + var titlefont: FontPartial + var autosize: Boolean + var showlegend: Boolean + var paper_bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var plot_bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var separators: String + var hidesources: Boolean + var xaxis: LayoutAxisPartial + var xaxis2: LayoutAxisPartial + var xaxis3: LayoutAxisPartial + var xaxis4: LayoutAxisPartial + var xaxis5: LayoutAxisPartial + var xaxis6: LayoutAxisPartial + var xaxis7: LayoutAxisPartial + var xaxis8: LayoutAxisPartial + var xaxis9: LayoutAxisPartial + var yaxis: LayoutAxisPartial + var yaxis2: LayoutAxisPartial + var yaxis3: LayoutAxisPartial + var yaxis4: LayoutAxisPartial + var yaxis5: LayoutAxisPartial + var yaxis6: LayoutAxisPartial + var yaxis7: LayoutAxisPartial + var yaxis8: LayoutAxisPartial + var yaxis9: LayoutAxisPartial + var margin: MarginPartial + var height: Number + var width: Number + var hovermode: dynamic /* 'closest' | 'x' | 'y' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var hoverlabel: HoverLabelPartial + var calendar: String /* 'gregorian' | 'chinese' | 'coptic' | 'discworld' | 'ethiopian' | 'hebrew' | 'islamic' | 'julian' | 'mayan' | 'nanakshahi' | 'nepali' | 'persian' | 'jalali' | 'taiwan' | 'thai' | 'ummalqura' */ + var xaxis.range: dynamic /* JsTuple<dynamic, dynamic> */ + get() = definedExternally + set(value) = definedExternally + var xaxis.range[0]: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var xaxis.range[1]: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var yaxis.range: dynamic /* JsTuple<dynamic, dynamic> */ + get() = definedExternally + set(value) = definedExternally + var yaxis.range[0]: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var yaxis.range[1]: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var yaxis.type: String /* '-' | 'linear' | 'log' | 'date' | 'category' */ + var xaxis.type: String /* '-' | 'linear' | 'log' | 'date' | 'category' */ + var xaxis.autorange: Boolean + var yaxis.autorange: Boolean + var xaxis.title: String + var yaxis.title: String + var ternary: Any + var geo: Any + var mapbox: Any + var radialaxis: AxisPartial + var angularaxis: Any + var dragmode: dynamic /* 'zoom' | 'pan' | 'select' | 'lasso' | 'orbit' | 'turntable' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var orientation: Number + var annotations: Array<AnnotationsPartial> + var shapes: Array<ShapePartial> + var images: Array<ImagePartial> + var updatemenus: Any + var sliders: Array<SliderPartial> + var legend: LegendPartial + var font: FontPartial + var scene: ScenePartial + var barmode: String /* 'stack' | 'group' | 'overlay' | 'relative' */ + var barnorm: String /* '' | 'fraction' | 'percent' */ + var bargap: String /* 0 | 1 */ + var bargroupgap: String /* 0 | 1 */ + var selectdirection: String /* 'h' | 'v' | 'd' | 'any' */ + var hiddenlabels: Array<String> + var grid: `T$4` + var polar: PolarLayoutPartial + var polar2: PolarLayoutPartial + var polar3: PolarLayoutPartial + var polar4: PolarLayoutPartial + var polar5: PolarLayoutPartial + var polar6: PolarLayoutPartial + var polar7: PolarLayoutPartial + var polar8: PolarLayoutPartial + var polar9: PolarLayoutPartial + var transition: Transition +} + +external interface LayoutPartial { + var title: dynamic /* String | `T$2` */ + get() = definedExternally + set(value) = definedExternally + var titlefont: Any? + get() = definedExternally + set(value) = definedExternally + var autosize: Boolean? + get() = definedExternally + set(value) = definedExternally + var showlegend: Boolean? + get() = definedExternally + set(value) = definedExternally + var paper_bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var plot_bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var separators: String? + get() = definedExternally + set(value) = definedExternally + var hidesources: Boolean? + get() = definedExternally + set(value) = definedExternally + var xaxis: Any? + get() = definedExternally + set(value) = definedExternally + var xaxis2: Any? + get() = definedExternally + set(value) = definedExternally + var xaxis3: Any? + get() = definedExternally + set(value) = definedExternally + var xaxis4: Any? + get() = definedExternally + set(value) = definedExternally + var xaxis5: Any? + get() = definedExternally + set(value) = definedExternally + var xaxis6: Any? + get() = definedExternally + set(value) = definedExternally + var xaxis7: Any? + get() = definedExternally + set(value) = definedExternally + var xaxis8: Any? + get() = definedExternally + set(value) = definedExternally + var xaxis9: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis2: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis3: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis4: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis5: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis6: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis7: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis8: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis9: Any? + get() = definedExternally + set(value) = definedExternally + var margin: Any? + get() = definedExternally + set(value) = definedExternally + var height: Number? + get() = definedExternally + set(value) = definedExternally + var width: Number? + get() = definedExternally + set(value) = definedExternally + var hovermode: dynamic /* 'closest' | 'x' | 'y' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var hoverlabel: Any? + get() = definedExternally + set(value) = definedExternally + var calendar: String /* 'gregorian' | 'chinese' | 'coptic' | 'discworld' | 'ethiopian' | 'hebrew' | 'islamic' | 'julian' | 'mayan' | 'nanakshahi' | 'nepali' | 'persian' | 'jalali' | 'taiwan' | 'thai' | 'ummalqura' */ + var xaxis.range: dynamic /* JsTuple<dynamic, dynamic> */ + get() = definedExternally + set(value) = definedExternally + var xaxis.range[0]: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var xaxis.range[1]: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var yaxis.range: dynamic /* JsTuple<dynamic, dynamic> */ + get() = definedExternally + set(value) = definedExternally + var yaxis.range[0]: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var yaxis.range[1]: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var yaxis.type: String /* '-' | 'linear' | 'log' | 'date' | 'category' */ + var xaxis.type: String /* '-' | 'linear' | 'log' | 'date' | 'category' */ + var xaxis.autorange: Boolean? + get() = definedExternally + set(value) = definedExternally + var yaxis.autorange: Boolean? + get() = definedExternally + set(value) = definedExternally + var xaxis.title: String? + get() = definedExternally + set(value) = definedExternally + var yaxis.title: String? + get() = definedExternally + set(value) = definedExternally + var ternary: Any? + get() = definedExternally + set(value) = definedExternally + var geo: Any? + get() = definedExternally + set(value) = definedExternally + var mapbox: Any? + get() = definedExternally + set(value) = definedExternally + var radialaxis: Any? + get() = definedExternally + set(value) = definedExternally + var angularaxis: Any? + get() = definedExternally + set(value) = definedExternally + var dragmode: dynamic /* 'zoom' | 'pan' | 'select' | 'lasso' | 'orbit' | 'turntable' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var orientation: Number? + get() = definedExternally + set(value) = definedExternally + var annotations: Array<Partial<Annotations>>? + get() = definedExternally + set(value) = definedExternally + var shapes: Array<Partial<Shape>>? + get() = definedExternally + set(value) = definedExternally + var images: Array<Partial<Image>>? + get() = definedExternally + set(value) = definedExternally + var updatemenus: Any? + get() = definedExternally + set(value) = definedExternally + var sliders: Array<Partial<Slider>>? + get() = definedExternally + set(value) = definedExternally + var legend: Any? + get() = definedExternally + set(value) = definedExternally + var font: Any? + get() = definedExternally + set(value) = definedExternally + var scene: Any? + get() = definedExternally + set(value) = definedExternally + var barmode: String /* 'stack' | 'group' | 'overlay' | 'relative' */ + var barnorm: String /* '' | 'fraction' | 'percent' */ + var bargap: String /* 0 | 1 */ + var bargroupgap: String /* 0 | 1 */ + var selectdirection: String /* 'h' | 'v' | 'd' | 'any' */ + var hiddenlabels: Array<String>? + get() = definedExternally + set(value) = definedExternally + var grid: `T$4`? + get() = definedExternally + set(value) = definedExternally + var polar: Any? + get() = definedExternally + set(value) = definedExternally + var polar2: Any? + get() = definedExternally + set(value) = definedExternally + var polar3: Any? + get() = definedExternally + set(value) = definedExternally + var polar4: Any? + get() = definedExternally + set(value) = definedExternally + var polar5: Any? + get() = definedExternally + set(value) = definedExternally + var polar6: Any? + get() = definedExternally + set(value) = definedExternally + var polar7: Any? + get() = definedExternally + set(value) = definedExternally + var polar8: Any? + get() = definedExternally + set(value) = definedExternally + var polar9: Any? + get() = definedExternally + set(value) = definedExternally + var transition: Transition? + get() = definedExternally + set(value) = definedExternally +} + +external interface Legend : Label { + var traceorder: String /* 'grouped' | 'normal' | 'reversed' */ + var x: Number + var y: Number + var borderwidth: Number + var orientation: String /* 'v' | 'h' */ + var tracegroupgap: Number + var xanchor: String /* 'auto' | 'left' | 'center' | 'right' */ + var yanchor: String /* 'auto' | 'top' | 'middle' | 'bottom' */ +} + +external interface LegendPartial : LabelPartial { + var traceorder: String /* 'grouped' | 'normal' | 'reversed' */ + var x: Number? + get() = definedExternally + set(value) = definedExternally + var y: Number? + get() = definedExternally + set(value) = definedExternally + var borderwidth: Number? + get() = definedExternally + set(value) = definedExternally + var orientation: String /* 'v' | 'h' */ + var tracegroupgap: Number? + get() = definedExternally + set(value) = definedExternally + var xanchor: String /* 'auto' | 'left' | 'center' | 'right' */ + var yanchor: String /* 'auto' | 'top' | 'middle' | 'bottom' */ +} + +external interface Axis { + var visible: Boolean + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var title: dynamic /* String | DataTitlePartial */ + get() = definedExternally + set(value) = definedExternally + var titlefont: FontPartial + var type: String /* '-' | 'linear' | 'log' | 'date' | 'category' */ + var autorange: dynamic /* Boolean | 'reversed' */ + get() = definedExternally + set(value) = definedExternally + var rangemode: String /* 'normal' | 'tozero' | 'nonnegative' */ + var range: Array<Any> + var tickmode: String /* 'auto' | 'linear' | 'array' */ + var nticks: Number + var tick0: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var dtick: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var tickvals: Array<Any> + var ticktext: Array<String> + var ticks: String /* 'outside' | 'inside' | '' */ + var mirror: dynamic /* Boolean | 'ticks' | 'all' | 'allticks' */ + get() = definedExternally + set(value) = definedExternally + var ticklen: Number + var tickwidth: Number + var tickcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var showticklabels: Boolean + var showspikes: Boolean + var spikecolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var spikethickness: Number + var categoryorder: String /* 'trace' | 'category ascending' | 'category descending' | 'array' | 'total ascending' | 'total descending' | 'min ascending' | 'min descending' | 'max ascending' | 'max descending' | 'sum ascending' | 'sum descending' | 'mean ascending' | 'mean descending' | 'median ascending' | 'median descending' */ + var categoryarray: Array<Any> + var tickfont: FontPartial + var tickangle: Number + var tickprefix: String + var showtickprefix: String /* 'all' | 'first' | 'last' | 'none' */ + var ticksuffix: String + var showticksuffix: String /* 'all' | 'first' | 'last' | 'none' */ + var showexponent: String /* 'all' | 'first' | 'last' | 'none' */ + var exponentformat: String /* 'none' | 'e' | 'E' | 'power' | 'SI' | 'B' */ + var separatethousands: Boolean + var tickformat: String + var hoverformat: String + var showline: Boolean + var linecolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var linewidth: Number + var showgrid: Boolean + var gridcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var gridwidth: Number + var zeroline: Boolean + var zerolinecolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var zerolinewidth: Number + var calendar: String /* 'gregorian' | 'chinese' | 'coptic' | 'discworld' | 'ethiopian' | 'hebrew' | 'islamic' | 'julian' | 'mayan' | 'nanakshahi' | 'nepali' | 'persian' | 'jalali' | 'taiwan' | 'thai' | 'ummalqura' */ +} + +external interface AxisPartial { + var visible: Boolean? + get() = definedExternally + set(value) = definedExternally + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var title: dynamic /* String | Partial<DataTitle> */ + get() = definedExternally + set(value) = definedExternally + var titlefont: Any? + get() = definedExternally + set(value) = definedExternally + var type: String /* '-' | 'linear' | 'log' | 'date' | 'category' */ + var autorange: dynamic /* Boolean | 'reversed' */ + get() = definedExternally + set(value) = definedExternally + var rangemode: String /* 'normal' | 'tozero' | 'nonnegative' */ + var range: Array<Any>? + get() = definedExternally + set(value) = definedExternally + var tickmode: String /* 'auto' | 'linear' | 'array' */ + var nticks: Number? + get() = definedExternally + set(value) = definedExternally + var tick0: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var dtick: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var tickvals: Array<Any>? + get() = definedExternally + set(value) = definedExternally + var ticktext: Array<String>? + get() = definedExternally + set(value) = definedExternally + var ticks: String /* 'outside' | 'inside' | '' */ + var mirror: dynamic /* Boolean | 'ticks' | 'all' | 'allticks' */ + get() = definedExternally + set(value) = definedExternally + var ticklen: Number? + get() = definedExternally + set(value) = definedExternally + var tickwidth: Number? + get() = definedExternally + set(value) = definedExternally + var tickcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var showticklabels: Boolean? + get() = definedExternally + set(value) = definedExternally + var showspikes: Boolean? + get() = definedExternally + set(value) = definedExternally + var spikecolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var spikethickness: Number? + get() = definedExternally + set(value) = definedExternally + var categoryorder: String /* 'trace' | 'category ascending' | 'category descending' | 'array' | 'total ascending' | 'total descending' | 'min ascending' | 'min descending' | 'max ascending' | 'max descending' | 'sum ascending' | 'sum descending' | 'mean ascending' | 'mean descending' | 'median ascending' | 'median descending' */ + var categoryarray: Array<Any>? + get() = definedExternally + set(value) = definedExternally + var tickfont: Any? + get() = definedExternally + set(value) = definedExternally + var tickangle: Number? + get() = definedExternally + set(value) = definedExternally + var tickprefix: String? + get() = definedExternally + set(value) = definedExternally + var showtickprefix: String /* 'all' | 'first' | 'last' | 'none' */ + var ticksuffix: String? + get() = definedExternally + set(value) = definedExternally + var showticksuffix: String /* 'all' | 'first' | 'last' | 'none' */ + var showexponent: String /* 'all' | 'first' | 'last' | 'none' */ + var exponentformat: String /* 'none' | 'e' | 'E' | 'power' | 'SI' | 'B' */ + var separatethousands: Boolean? + get() = definedExternally + set(value) = definedExternally + var tickformat: String? + get() = definedExternally + set(value) = definedExternally + var hoverformat: String? + get() = definedExternally + set(value) = definedExternally + var showline: Boolean? + get() = definedExternally + set(value) = definedExternally + var linecolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var linewidth: Number? + get() = definedExternally + set(value) = definedExternally + var showgrid: Boolean? + get() = definedExternally + set(value) = definedExternally + var gridcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var gridwidth: Number? + get() = definedExternally + set(value) = definedExternally + var zeroline: Boolean? + get() = definedExternally + set(value) = definedExternally + var zerolinecolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var zerolinewidth: Number? + get() = definedExternally + set(value) = definedExternally + var calendar: String /* 'gregorian' | 'chinese' | 'coptic' | 'discworld' | 'ethiopian' | 'hebrew' | 'islamic' | 'julian' | 'mayan' | 'nanakshahi' | 'nepali' | 'persian' | 'jalali' | 'taiwan' | 'thai' | 'ummalqura' */ +} + +external interface LayoutAxis : Axis { + var fixedrange: Boolean + var scaleanchor: String /* 'x' | 'x2' | 'x3' | 'x4' | 'x5' | 'x6' | 'x7' | 'x8' | 'x9' | 'y' | 'y2' | 'y3' | 'y4' | 'y5' | 'y6' | 'y7' | 'y8' | 'y9' */ + var scaleratio: Number + var constrain: String /* 'range' | 'domain' */ + var constraintoward: String /* 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom' */ + var spikedash: String + var spikemode: String + var anchor: String /* 'free' | 'x' | 'x2' | 'x3' | 'x4' | 'x5' | 'x6' | 'x7' | 'x8' | 'x9' | 'y' | 'y2' | 'y3' | 'y4' | 'y5' | 'y6' | 'y7' | 'y8' | 'y9' */ + var side: String /* 'top' | 'bottom' | 'left' | 'right' | 'clockwise' | 'counterclockwise' */ + var overlaying: String /* 'free' | 'x' | 'x2' | 'x3' | 'x4' | 'x5' | 'x6' | 'x7' | 'x8' | 'x9' | 'y' | 'y2' | 'y3' | 'y4' | 'y5' | 'y6' | 'y7' | 'y8' | 'y9' */ + var layer: String /* 'above traces' | 'below traces' */ + var domain: Array<Number> + var position: Number + var rangeslider: RangeSliderPartial + var rangeselector: RangeSelectorPartial + var automargin: Boolean + var autotick: Boolean + var angle: Any +} + +external interface LayoutAxisPartial : AxisPartial { + var fixedrange: Boolean? + get() = definedExternally + set(value) = definedExternally + var scaleanchor: String /* 'x' | 'x2' | 'x3' | 'x4' | 'x5' | 'x6' | 'x7' | 'x8' | 'x9' | 'y' | 'y2' | 'y3' | 'y4' | 'y5' | 'y6' | 'y7' | 'y8' | 'y9' */ + var scaleratio: Number? + get() = definedExternally + set(value) = definedExternally + var constrain: String /* 'range' | 'domain' */ + var constraintoward: String /* 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom' */ + var spikedash: String? + get() = definedExternally + set(value) = definedExternally + var spikemode: String? + get() = definedExternally + set(value) = definedExternally + var anchor: String /* 'free' | 'x' | 'x2' | 'x3' | 'x4' | 'x5' | 'x6' | 'x7' | 'x8' | 'x9' | 'y' | 'y2' | 'y3' | 'y4' | 'y5' | 'y6' | 'y7' | 'y8' | 'y9' */ + var side: String /* 'top' | 'bottom' | 'left' | 'right' | 'clockwise' | 'counterclockwise' */ + var overlaying: String /* 'free' | 'x' | 'x2' | 'x3' | 'x4' | 'x5' | 'x6' | 'x7' | 'x8' | 'x9' | 'y' | 'y2' | 'y3' | 'y4' | 'y5' | 'y6' | 'y7' | 'y8' | 'y9' */ + var layer: String /* 'above traces' | 'below traces' */ + var domain: Array<Number>? + get() = definedExternally + set(value) = definedExternally + var position: Number? + get() = definedExternally + set(value) = definedExternally + var rangeslider: Any? + get() = definedExternally + set(value) = definedExternally + var rangeselector: Any? + get() = definedExternally + set(value) = definedExternally + var automargin: Boolean? + get() = definedExternally + set(value) = definedExternally + var autotick: Boolean? + get() = definedExternally + set(value) = definedExternally + var angle: Any? + get() = definedExternally + set(value) = definedExternally +} + +external interface SceneAxis : Axis { + var spikesides: Boolean + var showbackground: Boolean + var backgroundcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var showaxeslabels: Boolean +} + +external interface SceneAxisPartial : AxisPartial { + var spikesides: Boolean? + get() = definedExternally + set(value) = definedExternally + var showbackground: Boolean? + get() = definedExternally + set(value) = definedExternally + var backgroundcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var showaxeslabels: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface ShapeLine { + var color: String + var width: Number + var dash: String /* 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot' */ +} + +external interface ShapeLinePartial { + var color: String? + get() = definedExternally + set(value) = definedExternally + var width: Number? + get() = definedExternally + set(value) = definedExternally + var dash: String /* 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot' */ +} + +external interface Shape { + var visible: Boolean + var layer: String /* 'below' | 'above' */ + var type: String /* 'rect' | 'circle' | 'line' | 'path' */ + var path: String + var xref: String /* 'x' | 'paper' */ + var xsizemode: String /* "scaled" | "pixel" */ + var xanchor: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var yref: String /* 'paper' | 'y' */ + var ysizemode: String /* "scaled" | "pixel" */ + var yanchor: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var x0: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var y0: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var x1: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var y1: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var fillcolor: String + var name: String + var templateitemname: String + var opacity: Number + var line: ShapeLinePartial +} + +external interface ShapePartial { + var visible: Boolean? + get() = definedExternally + set(value) = definedExternally + var layer: String /* 'below' | 'above' */ + var type: String /* 'rect' | 'circle' | 'line' | 'path' */ + var path: String? + get() = definedExternally + set(value) = definedExternally + var xref: String /* 'x' | 'paper' */ + var xsizemode: String /* "scaled" | "pixel" */ + var xanchor: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var yref: String /* 'paper' | 'y' */ + var ysizemode: String /* "scaled" | "pixel" */ + var yanchor: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var x0: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var y0: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var x1: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var y1: dynamic /* String | Number | Date | Nothing? */ + get() = definedExternally + set(value) = definedExternally + var fillcolor: String? + get() = definedExternally + set(value) = definedExternally + var name: String? + get() = definedExternally + set(value) = definedExternally + var templateitemname: String? + get() = definedExternally + set(value) = definedExternally + var opacity: Number? + get() = definedExternally + set(value) = definedExternally + var line: Any? + get() = definedExternally + set(value) = definedExternally +} + +external interface Margin { + var t: Number + var b: Number + var l: Number + var r: Number + var pad: Number +} + +external interface MarginPartial { + var t: Number? + get() = definedExternally + set(value) = definedExternally + var b: Number? + get() = definedExternally + set(value) = definedExternally + var l: Number? + get() = definedExternally + set(value) = definedExternally + var r: Number? + get() = definedExternally + set(value) = definedExternally + var pad: Number? + get() = definedExternally + set(value) = definedExternally +} + +typealias ButtonClickEvent = (gd: PlotlyHTMLElement, ev: MouseEvent) -> Unit + +external interface Icon { + var height: Number? + get() = definedExternally + set(value) = definedExternally + var width: Number? + get() = definedExternally + set(value) = definedExternally + var ascent: Number? + get() = definedExternally + set(value) = definedExternally + var descent: Number? + get() = definedExternally + set(value) = definedExternally + var name: String? + get() = definedExternally + set(value) = definedExternally + var path: String? + get() = definedExternally + set(value) = definedExternally + var svg: String? + get() = definedExternally + set(value) = definedExternally + var transform: String? + get() = definedExternally + set(value) = definedExternally +} + +external interface ModeBarButton { + var name: String + var title: String + var icon: dynamic /* String | Icon */ + get() = definedExternally + set(value) = definedExternally + var gravity: String? + get() = definedExternally + set(value) = definedExternally + var click: ButtonClickEvent + var attr: String? + get() = definedExternally + set(value) = definedExternally + var `val`: Any? + get() = definedExternally + set(value) = definedExternally + var toggle: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface GaugeLine { + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var width: Number +} + +external interface GaugeLinePartial { + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var width: Number? + get() = definedExternally + set(value) = definedExternally +} + +external interface Threshold { + var line: GaugeLinePartial + var value: Number + var thickness: Number +} + +external interface ThresholdPartial { + var line: Any? + get() = definedExternally + set(value) = definedExternally + var value: Number? + get() = definedExternally + set(value) = definedExternally + var thickness: Number? + get() = definedExternally + set(value) = definedExternally +} + +external interface GaugeBar { + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var line: GaugeLinePartial + var thickness: Number +} + +external interface GaugeBarPartial { + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var line: Any? + get() = definedExternally + set(value) = definedExternally + var thickness: Number? + get() = definedExternally + set(value) = definedExternally +} + +external interface `T$5` { + var range: Array<Number> + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally +} + +external interface Gauge { + var shape: String /* 'angular' | 'bullet' */ + var bar: GaugeBarPartial + var bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var bordercolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var borderwidth: Number + var axis: AxisPartial + var steps: Array<`T$5`> + var threshold: ThresholdPartial +} + +external interface GaugePartial { + var shape: String /* 'angular' | 'bullet' */ + var bar: Any? + get() = definedExternally + set(value) = definedExternally + var bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var bordercolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var borderwidth: Number? + get() = definedExternally + set(value) = definedExternally + var axis: Any? + get() = definedExternally + set(value) = definedExternally + var steps: Array<`T$5`>? + get() = definedExternally + set(value) = definedExternally + var threshold: Any? + get() = definedExternally + set(value) = definedExternally +} + +external interface `T$6` { + var symbol: String + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally +} + +external interface Delta { + var reference: Number + var position: String /* 'top' | 'bottom' | 'left' | 'right' */ + var relative: Boolean + var valueformat: String + var increasing: `T$6` + var decreasing: `T$6` +} + +external interface DeltaPartial { + var reference: Number? + get() = definedExternally + set(value) = definedExternally + var position: String /* 'top' | 'bottom' | 'left' | 'right' */ + var relative: Boolean? + get() = definedExternally + set(value) = definedExternally + var valueformat: String? + get() = definedExternally + set(value) = definedExternally + var increasing: `T$6`? + get() = definedExternally + set(value) = definedExternally + var decreasing: `T$6`? + get() = definedExternally + set(value) = definedExternally +} + +external interface DataTitle { + var text: String + var font: FontPartial + var position: String /* "top left" | "top center" | "top right" | "middle center" | "bottom left" | "bottom center" | "bottom right" */ +} + +external interface DataTitlePartial { + var text: String? + get() = definedExternally + set(value) = definedExternally + var font: Any? + get() = definedExternally + set(value) = definedExternally + var position: String /* "top left" | "top center" | "top right" | "middle center" | "bottom left" | "bottom center" | "bottom right" */ +} + +external interface PlotNumber { + var valueformat: String + var font: FontPartial + var prefix: String + var suffix: String +} + +external interface PlotNumberPartial { + var valueformat: String? + get() = definedExternally + set(value) = definedExternally + var font: Any? + get() = definedExternally + set(value) = definedExternally + var prefix: String? + get() = definedExternally + set(value) = definedExternally + var suffix: String? + get() = definedExternally + set(value) = definedExternally +} + +external interface ErrorOptions { + var visible: Boolean + var symmetric: Boolean + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var thickness: Number + var width: Number + var opacity: Number +} + +external interface ErrorOptionsPartial { + var visible: Boolean? + get() = definedExternally + set(value) = definedExternally + var symmetric: Boolean? + get() = definedExternally + set(value) = definedExternally + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var thickness: Number? + get() = definedExternally + set(value) = definedExternally + var width: Number? + get() = definedExternally + set(value) = definedExternally + var opacity: Number? + get() = definedExternally + set(value) = definedExternally +} + +typealias Data = PlotDataPartial + +typealias DataTransform = TransformPartial + +typealias ScatterData = PlotData + +external interface `T$7` { + var start: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var end: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var size: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally +} + +external interface `T$8` { + var rows: Number? + get() = definedExternally + set(value) = definedExternally + var columns: Number? + get() = definedExternally + set(value) = definedExternally + var x: Array<Number>? + get() = definedExternally + set(value) = definedExternally + var y: Array<Number>? + get() = definedExternally + set(value) = definedExternally +} + +external interface PlotData { + var type: String /* 'bar' | 'box' | 'candlestick' | 'choropleth' | 'contour' | 'heatmap' | 'histogram' | 'indicator' | 'mesh3d' | 'ohlc' | 'parcoords' | 'pie' | 'pointcloud' | 'scatter' | 'scatter3d' | 'scattergeo' | 'scattergl' | 'scatterpolar' | 'scatterternary' | 'surface' | 'treemap' | 'waterfall' | 'funnel' | 'funnelarea' */ + var x: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var y: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var z: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Array<Array<Array<dynamic /* String | Number | Date | Nothing? */>>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var xy: Float32Array + var error_x: ErrorOptionsPartial /* ErrorOptionsPartial & dynamic */ + var error_y: ErrorOptionsPartial /* ErrorOptionsPartial & dynamic */ + var xaxis: String + var yaxis: String + var text: dynamic /* String | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var line: ScatterLinePartial + var line.color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var line.width: Number + var line.dash: String /* 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot' */ + var line.shape: String /* 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv' */ + var line.smoothing: Number + var line.simplify: Boolean + var marker: PlotMarkerPartial + var marker.symbol: dynamic /* String | Number | Array<dynamic /* String | Number */> | Array<dynamic /* String | Number | Array<dynamic /* String | Number */> */> */ + get() = definedExternally + set(value) = definedExternally + var marker.color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var marker.colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> | Array<dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */> */ + get() = definedExternally + set(value) = definedExternally + var marker.opacity: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var marker.size: dynamic /* Number | Array<Number> | Array<Array<Number>> */ + get() = definedExternally + set(value) = definedExternally + var marker.maxdisplayed: Number + var marker.sizeref: Number + var marker.sizemax: Number + var marker.sizemin: Number + var marker.sizemode: String /* 'diameter' | 'area' */ + var marker.showscale: Boolean + var marker.line: ScatterMarkerLinePartial + var marker.line.color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var marker.line.colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> | Array<dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */> */ + get() = definedExternally + set(value) = definedExternally + var marker.colorbar: Any + var marker.pad.t: Number + var marker.pad.b: Number + var marker.pad.l: Number + var marker.pad.r: Number + var mode: String /* 'lines' | 'markers' | 'text' | 'lines+markers' | 'text+markers' | 'text+lines' | 'text+lines+markers' | 'none' | 'gauge' | 'number' | 'delta' | 'number+delta' | 'gauge+number' | 'gauge+number+delta' | 'gauge+delta' */ + var hoveron: String /* 'points' | 'fills' */ + var hoverinfo: String /* 'all' | 'name' | 'none' | 'skip' | 'text' | 'x' | 'x+text' | 'x+name' | 'x+y' | 'x+y+text' | 'x+y+name' | 'x+y+z' | 'x+y+z+text' | 'x+y+z+name' | 'y+name' | 'y+x' | 'y+text' | 'y+x+text' | 'y+x+name' | 'y+z' | 'y+z+text' | 'y+z+name' | 'y+x+z' | 'y+x+z+text' | 'y+x+z+name' | 'z+x' | 'z+x+text' | 'z+x+name' | 'z+y+x' | 'z+y+x+text' | 'z+y+x+name' | 'z+x+y' | 'z+x+y+text' | 'z+x+y+name' */ + var hoverlabel: HoverLabelPartial + var hovertemplate: dynamic /* String | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var hovertext: dynamic /* String | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var textinfo: String /* 'label' | 'label+text' | 'label+value' | 'label+percent' | 'label+text+value' | 'label+text+percent' | 'label+value+percent' | 'text' | 'text+value' | 'text+percent' | 'text+value+percent' | 'value' | 'value+percent' | 'percent' | 'none' */ + var textposition: String /* "top left" | "top center" | "top right" | "middle left" | "middle center" | "middle right" | "bottom left" | "bottom center" | "bottom right" | "inside" | "outside" */ + var textfont: FontPartial + var fill: String /* 'none' | 'tozeroy' | 'tozerox' | 'tonexty' | 'tonextx' | 'toself' | 'tonext' */ + var fillcolor: String + var showlegend: Boolean + var legendgroup: String + var parents: Array<String> + var name: String + var stackgroup: String + var connectgaps: Boolean + var visible: dynamic /* Boolean | 'legendonly' */ + get() = definedExternally + set(value) = definedExternally + var delta: DeltaPartial + var gauge: GaugePartial + var number: PlotNumberPartial + var transforms: Array<DataTransform> + var orientation: String /* 'v' | 'h' */ + var width: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var boxmean: dynamic /* Boolean | 'sd' */ + get() = definedExternally + set(value) = definedExternally + var opacity: Number + var showscale: Boolean + var colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */ + get() = definedExternally + set(value) = definedExternally + var zsmooth: dynamic /* 'fast' | 'best' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var ygap: Number + var xgap: Number + var transpose: Boolean + var autobinx: Boolean + var xbins: `T$7` + var value: Number + var values: Array<dynamic /* String | Number | Date | Nothing? */> + var labels: Array<dynamic /* String | Number | Date | Nothing? */> + var direction: String /* 'clockwise' | 'counterclockwise' */ + var hole: Number + var rotation: Number + var theta: Array<dynamic /* String | Number | Date | Nothing? */> + var r: Array<dynamic /* String | Number | Date | Nothing? */> + var customdata: Array<dynamic /* String | Number | Date | Nothing? */> + var domain: `T$8` + var title: DataTitlePartial +} + +external interface PlotDataPartial { + var type: String /* 'bar' | 'box' | 'candlestick' | 'choropleth' | 'contour' | 'heatmap' | 'histogram' | 'indicator' | 'mesh3d' | 'ohlc' | 'parcoords' | 'pie' | 'pointcloud' | 'scatter' | 'scatter3d' | 'scattergeo' | 'scattergl' | 'scatterpolar' | 'scatterternary' | 'surface' | 'treemap' | 'waterfall' | 'funnel' | 'funnelarea' */ + var x: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var y: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var z: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Array<Array<Array<dynamic /* String | Number | Date | Nothing? */>>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var xy: Float32Array? + get() = definedExternally + set(value) = definedExternally + var error_x: ErrorOptionsPartial /* ErrorOptionsPartial & dynamic */ + var error_y: ErrorOptionsPartial /* ErrorOptionsPartial & dynamic */ + var xaxis: String? + get() = definedExternally + set(value) = definedExternally + var yaxis: String? + get() = definedExternally + set(value) = definedExternally + var text: dynamic /* String | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var line: Any? + get() = definedExternally + set(value) = definedExternally + var line.color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var line.width: Number? + get() = definedExternally + set(value) = definedExternally + var line.dash: String /* 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot' */ + var line.shape: String /* 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv' */ + var line.smoothing: Number? + get() = definedExternally + set(value) = definedExternally + var line.simplify: Boolean? + get() = definedExternally + set(value) = definedExternally + var marker: Any? + get() = definedExternally + set(value) = definedExternally + var marker.symbol: dynamic /* String | Number | Array<dynamic /* String | Number */> | Array<dynamic /* String | Number | Array<dynamic /* String | Number */> */> */ + get() = definedExternally + set(value) = definedExternally + var marker.color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var marker.colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> | Array<dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */> */ + get() = definedExternally + set(value) = definedExternally + var marker.opacity: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var marker.size: dynamic /* Number | Array<Number> | Array<Array<Number>> */ + get() = definedExternally + set(value) = definedExternally + var marker.maxdisplayed: Number? + get() = definedExternally + set(value) = definedExternally + var marker.sizeref: Number? + get() = definedExternally + set(value) = definedExternally + var marker.sizemax: Number? + get() = definedExternally + set(value) = definedExternally + var marker.sizemin: Number? + get() = definedExternally + set(value) = definedExternally + var marker.sizemode: String /* 'diameter' | 'area' */ + var marker.showscale: Boolean? + get() = definedExternally + set(value) = definedExternally + var marker.line: Any? + get() = definedExternally + set(value) = definedExternally + var marker.line.color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var marker.line.colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> | Array<dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */> */ + get() = definedExternally + set(value) = definedExternally + var marker.colorbar: Any? + get() = definedExternally + set(value) = definedExternally + var marker.pad.t: Number? + get() = definedExternally + set(value) = definedExternally + var marker.pad.b: Number? + get() = definedExternally + set(value) = definedExternally + var marker.pad.l: Number? + get() = definedExternally + set(value) = definedExternally + var marker.pad.r: Number? + get() = definedExternally + set(value) = definedExternally + var mode: String /* 'lines' | 'markers' | 'text' | 'lines+markers' | 'text+markers' | 'text+lines' | 'text+lines+markers' | 'none' | 'gauge' | 'number' | 'delta' | 'number+delta' | 'gauge+number' | 'gauge+number+delta' | 'gauge+delta' */ + var hoveron: String /* 'points' | 'fills' */ + var hoverinfo: String /* 'all' | 'name' | 'none' | 'skip' | 'text' | 'x' | 'x+text' | 'x+name' | 'x+y' | 'x+y+text' | 'x+y+name' | 'x+y+z' | 'x+y+z+text' | 'x+y+z+name' | 'y+name' | 'y+x' | 'y+text' | 'y+x+text' | 'y+x+name' | 'y+z' | 'y+z+text' | 'y+z+name' | 'y+x+z' | 'y+x+z+text' | 'y+x+z+name' | 'z+x' | 'z+x+text' | 'z+x+name' | 'z+y+x' | 'z+y+x+text' | 'z+y+x+name' | 'z+x+y' | 'z+x+y+text' | 'z+x+y+name' */ + var hoverlabel: Any? + get() = definedExternally + set(value) = definedExternally + var hovertemplate: dynamic /* String | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var hovertext: dynamic /* String | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var textinfo: String /* 'label' | 'label+text' | 'label+value' | 'label+percent' | 'label+text+value' | 'label+text+percent' | 'label+value+percent' | 'text' | 'text+value' | 'text+percent' | 'text+value+percent' | 'value' | 'value+percent' | 'percent' | 'none' */ + var textposition: String /* "top left" | "top center" | "top right" | "middle left" | "middle center" | "middle right" | "bottom left" | "bottom center" | "bottom right" | "inside" | "outside" */ + var textfont: Any? + get() = definedExternally + set(value) = definedExternally + var fill: String /* 'none' | 'tozeroy' | 'tozerox' | 'tonexty' | 'tonextx' | 'toself' | 'tonext' */ + var fillcolor: String? + get() = definedExternally + set(value) = definedExternally + var showlegend: Boolean? + get() = definedExternally + set(value) = definedExternally + var legendgroup: String? + get() = definedExternally + set(value) = definedExternally + var parents: Array<String>? + get() = definedExternally + set(value) = definedExternally + var name: String? + get() = definedExternally + set(value) = definedExternally + var stackgroup: String? + get() = definedExternally + set(value) = definedExternally + var connectgaps: Boolean? + get() = definedExternally + set(value) = definedExternally + var visible: dynamic /* Boolean | 'legendonly' */ + get() = definedExternally + set(value) = definedExternally + var delta: Any? + get() = definedExternally + set(value) = definedExternally + var gauge: Any? + get() = definedExternally + set(value) = definedExternally + var number: Any? + get() = definedExternally + set(value) = definedExternally + var transforms: Array<DataTransform>? + get() = definedExternally + set(value) = definedExternally + var orientation: String /* 'v' | 'h' */ + var width: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var boxmean: dynamic /* Boolean | 'sd' */ + get() = definedExternally + set(value) = definedExternally + var opacity: Number? + get() = definedExternally + set(value) = definedExternally + var showscale: Boolean? + get() = definedExternally + set(value) = definedExternally + var colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */ + get() = definedExternally + set(value) = definedExternally + var zsmooth: dynamic /* 'fast' | 'best' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var ygap: Number? + get() = definedExternally + set(value) = definedExternally + var xgap: Number? + get() = definedExternally + set(value) = definedExternally + var transpose: Boolean? + get() = definedExternally + set(value) = definedExternally + var autobinx: Boolean? + get() = definedExternally + set(value) = definedExternally + var xbins: `T$7`? + get() = definedExternally + set(value) = definedExternally + var value: Number? + get() = definedExternally + set(value) = definedExternally + var values: Array<dynamic /* String | Number | Date | Nothing? */>? + get() = definedExternally + set(value) = definedExternally + var labels: Array<dynamic /* String | Number | Date | Nothing? */>? + get() = definedExternally + set(value) = definedExternally + var direction: String /* 'clockwise' | 'counterclockwise' */ + var hole: Number? + get() = definedExternally + set(value) = definedExternally + var rotation: Number? + get() = definedExternally + set(value) = definedExternally + var theta: Array<dynamic /* String | Number | Date | Nothing? */>? + get() = definedExternally + set(value) = definedExternally + var r: Array<dynamic /* String | Number | Date | Nothing? */>? + get() = definedExternally + set(value) = definedExternally + var customdata: Array<dynamic /* String | Number | Date | Nothing? */>? + get() = definedExternally + set(value) = definedExternally + var domain: `T$8`? + get() = definedExternally + set(value) = definedExternally + var title: Any? + get() = definedExternally + set(value) = definedExternally +} + +external interface TransformStyle { + var target: dynamic /* Number | String | Array<Number> | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var value: PlotDataPartial +} + +external interface TransformAggregation { + var target: String + var func: String /* 'count' | 'sum' | 'avg' | 'median' | 'mode' | 'rms' | 'stddev' | 'min' | 'max' | 'first' | 'last' */ + var funcmode: String /* 'sample' | 'population' */ + var enabled: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface Transform { + var type: String /* 'aggregate' | 'filter' | 'groupby' | 'sort' */ + var enabled: Boolean + var target: dynamic /* Number | String | Array<Number> | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var operation: String + var aggregations: Array<TransformAggregation> + var preservegaps: Boolean + var groups: dynamic /* String | Array<Number> | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var nameformat: String + var styles: Array<TransformStyle> + var value: Any + var order: String /* 'ascending' | 'descending' */ +} + +external interface TransformPartial { + var type: String /* 'aggregate' | 'filter' | 'groupby' | 'sort' */ + var enabled: Boolean? + get() = definedExternally + set(value) = definedExternally + var target: dynamic /* Number | String | Array<Number> | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var operation: String? + get() = definedExternally + set(value) = definedExternally + var aggregations: Array<TransformAggregation>? + get() = definedExternally + set(value) = definedExternally + var preservegaps: Boolean? + get() = definedExternally + set(value) = definedExternally + var groups: dynamic /* String | Array<Number> | Array<String> */ + get() = definedExternally + set(value) = definedExternally + var nameformat: String? + get() = definedExternally + set(value) = definedExternally + var styles: Array<TransformStyle>? + get() = definedExternally + set(value) = definedExternally + var value: Any? + get() = definedExternally + set(value) = definedExternally + var order: String /* 'ascending' | 'descending' */ +} + +external interface `T$9` { + var dtickrange: Array<Any> + var value: String +} + +external interface ColorBar { + var thicknessmode: String /* 'fraction' | 'pixels' */ + var thickness: Number + var lenmode: String /* 'fraction' | 'pixels' */ + var len: Number + var x: Number + var xanchor: String /* 'left' | 'center' | 'right' */ + var xpad: Number + var y: Number + var yanchor: String /* 'top' | 'middle' | 'bottom' */ + var ypad: Number + var outlinecolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var outlinewidth: Number + var bordercolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var borderwidth: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var tickmode: String /* 'auto' | 'linear' | 'array' */ + var nticks: Number + var tick0: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var dtick: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var tickvals: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Array<Array<Array<dynamic /* String | Number | Date | Nothing? */>>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var ticktext: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Array<Array<Array<dynamic /* String | Number | Date | Nothing? */>>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var ticks: String /* 'outside' | 'inside' | '' */ + var ticklen: Number + var tickwidth: Number + var tickcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var showticklabels: Boolean + var tickfont: Font + var tickangle: Number + var tickformat: String + var tickformatstops: `T$9` + var tickprefix: String + var showtickprefix: String /* 'all' | 'first' | 'last' | 'none' */ + var ticksuffix: String + var showticksuffix: String /* 'all' | 'first' | 'last' | 'none' */ + var separatethousands: Boolean + var exponentformat: String /* 'none' | 'e' | 'E' | 'power' | 'SI' | 'B' */ + var showexponent: String /* 'all' | 'first' | 'last' | 'none' */ + var title: String + var titlefont: Font + var titleside: String /* 'right' | 'top' | 'bottom' */ + var tickvalssrc: Any + var ticktextsrc: Any +} + +external interface ColorBarPartial { + var thicknessmode: String /* 'fraction' | 'pixels' */ + var thickness: Number? + get() = definedExternally + set(value) = definedExternally + var lenmode: String /* 'fraction' | 'pixels' */ + var len: Number? + get() = definedExternally + set(value) = definedExternally + var x: Number? + get() = definedExternally + set(value) = definedExternally + var xanchor: String /* 'left' | 'center' | 'right' */ + var xpad: Number? + get() = definedExternally + set(value) = definedExternally + var y: Number? + get() = definedExternally + set(value) = definedExternally + var yanchor: String /* 'top' | 'middle' | 'bottom' */ + var ypad: Number? + get() = definedExternally + set(value) = definedExternally + var outlinecolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var outlinewidth: Number? + get() = definedExternally + set(value) = definedExternally + var bordercolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var borderwidth: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var tickmode: String /* 'auto' | 'linear' | 'array' */ + var nticks: Number? + get() = definedExternally + set(value) = definedExternally + var tick0: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var dtick: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var tickvals: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Array<Array<Array<dynamic /* String | Number | Date | Nothing? */>>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var ticktext: dynamic /* Array<dynamic /* String | Number | Date | Nothing? */> | Array<Array<dynamic /* String | Number | Date | Nothing? */>> | Array<Array<Array<dynamic /* String | Number | Date | Nothing? */>>> | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array */ + get() = definedExternally + set(value) = definedExternally + var ticks: String /* 'outside' | 'inside' | '' */ + var ticklen: Number? + get() = definedExternally + set(value) = definedExternally + var tickwidth: Number? + get() = definedExternally + set(value) = definedExternally + var tickcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var showticklabels: Boolean? + get() = definedExternally + set(value) = definedExternally + var tickfont: Font? + get() = definedExternally + set(value) = definedExternally + var tickangle: Number? + get() = definedExternally + set(value) = definedExternally + var tickformat: String? + get() = definedExternally + set(value) = definedExternally + var tickformatstops: `T$9`? + get() = definedExternally + set(value) = definedExternally + var tickprefix: String? + get() = definedExternally + set(value) = definedExternally + var showtickprefix: String /* 'all' | 'first' | 'last' | 'none' */ + var ticksuffix: String? + get() = definedExternally + set(value) = definedExternally + var showticksuffix: String /* 'all' | 'first' | 'last' | 'none' */ + var separatethousands: Boolean? + get() = definedExternally + set(value) = definedExternally + var exponentformat: String /* 'none' | 'e' | 'E' | 'power' | 'SI' | 'B' */ + var showexponent: String /* 'all' | 'first' | 'last' | 'none' */ + var title: String? + get() = definedExternally + set(value) = definedExternally + var titlefont: Font? + get() = definedExternally + set(value) = definedExternally + var titleside: String /* 'right' | 'top' | 'bottom' */ + var tickvalssrc: Any? + get() = definedExternally + set(value) = definedExternally + var ticktextsrc: Any? + get() = definedExternally + set(value) = definedExternally +} + +external interface `T$10` { + var type: String /* 'radial' | 'horizontal' | 'vertical' | 'none' */ + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var typesrc: Any + var colorsrc: Any +} + +external interface PlotMarker { + var symbol: dynamic /* String | Number | Array<dynamic /* String | Number */> */ + get() = definedExternally + set(value) = definedExternally + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> | Array<dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */> */ + get() = definedExternally + set(value) = definedExternally + var colors: Array<dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */> + var colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */ + get() = definedExternally + set(value) = definedExternally + var cauto: Boolean + var cmax: Number + var cmin: Number + var autocolorscale: Boolean + var reversescale: Boolean + var opacity: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var size: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var maxdisplayed: Number + var sizeref: Number + var sizemax: Number + var sizemin: Number + var sizemode: String /* 'diameter' | 'area' */ + var showscale: Boolean + var line: ScatterMarkerLinePartial + var pad: PaddingPartial + var width: Number + var colorbar: ColorBarPartial + var gradient: `T$10` +} + +external interface PlotMarkerPartial { + var symbol: dynamic /* String | Number | Array<dynamic /* String | Number */> */ + get() = definedExternally + set(value) = definedExternally + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> | Array<dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */> */ + get() = definedExternally + set(value) = definedExternally + var colors: Array<dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */>? + get() = definedExternally + set(value) = definedExternally + var colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */ + get() = definedExternally + set(value) = definedExternally + var cauto: Boolean? + get() = definedExternally + set(value) = definedExternally + var cmax: Number? + get() = definedExternally + set(value) = definedExternally + var cmin: Number? + get() = definedExternally + set(value) = definedExternally + var autocolorscale: Boolean? + get() = definedExternally + set(value) = definedExternally + var reversescale: Boolean? + get() = definedExternally + set(value) = definedExternally + var opacity: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var size: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var maxdisplayed: Number? + get() = definedExternally + set(value) = definedExternally + var sizeref: Number? + get() = definedExternally + set(value) = definedExternally + var sizemax: Number? + get() = definedExternally + set(value) = definedExternally + var sizemin: Number? + get() = definedExternally + set(value) = definedExternally + var sizemode: String /* 'diameter' | 'area' */ + var showscale: Boolean? + get() = definedExternally + set(value) = definedExternally + var line: Any? + get() = definedExternally + set(value) = definedExternally + var pad: Any? + get() = definedExternally + set(value) = definedExternally + var width: Number? + get() = definedExternally + set(value) = definedExternally + var colorbar: Any? + get() = definedExternally + set(value) = definedExternally + var gradient: `T$10`? + get() = definedExternally + set(value) = definedExternally +} + +typealias ScatterMarker = PlotMarker + +external interface ScatterMarkerLine { + var width: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */ + get() = definedExternally + set(value) = definedExternally + var cauto: Boolean + var cmax: Number + var cmin: Number + var autocolorscale: Boolean + var reversescale: Boolean +} + +external interface ScatterMarkerLinePartial { + var width: dynamic /* Number | Array<Number> */ + get() = definedExternally + set(value) = definedExternally + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var colorscale: dynamic /* String | Array<String> | Array<dynamic /* JsTuple<Number, String> */> */ + get() = definedExternally + set(value) = definedExternally + var cauto: Boolean? + get() = definedExternally + set(value) = definedExternally + var cmax: Number? + get() = definedExternally + set(value) = definedExternally + var cmin: Number? + get() = definedExternally + set(value) = definedExternally + var autocolorscale: Boolean? + get() = definedExternally + set(value) = definedExternally + var reversescale: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface ScatterLine { + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var width: Number + var dash: String /* 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot' */ + var shape: String /* 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv' */ + var smoothing: Number + var simplify: Boolean +} + +external interface ScatterLinePartial { + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var width: Number? + get() = definedExternally + set(value) = definedExternally + var dash: String /* 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot' */ + var shape: String /* 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv' */ + var smoothing: Number? + get() = definedExternally + set(value) = definedExternally + var simplify: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface Font { + var family: String + var size: Number + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally +} + +external interface FontPartial { + var family: String? + get() = definedExternally + set(value) = definedExternally + var size: Number? + get() = definedExternally + set(value) = definedExternally + var color: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally +} + +external interface Edits { + var annotationPosition: Boolean + var annotationTail: Boolean + var annotationText: Boolean + var axisTitleText: Boolean + var colorbarPosition: Boolean + var colorbarTitleText: Boolean + var legendPosition: Boolean + var legendText: Boolean + var shapePosition: Boolean + var titleText: Boolean +} + +external interface EditsPartial { + var annotationPosition: Boolean? + get() = definedExternally + set(value) = definedExternally + var annotationTail: Boolean? + get() = definedExternally + set(value) = definedExternally + var annotationText: Boolean? + get() = definedExternally + set(value) = definedExternally + var axisTitleText: Boolean? + get() = definedExternally + set(value) = definedExternally + var colorbarPosition: Boolean? + get() = definedExternally + set(value) = definedExternally + var colorbarTitleText: Boolean? + get() = definedExternally + set(value) = definedExternally + var legendPosition: Boolean? + get() = definedExternally + set(value) = definedExternally + var legendText: Boolean? + get() = definedExternally + set(value) = definedExternally + var shapePosition: Boolean? + get() = definedExternally + set(value) = definedExternally + var titleText: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface `T$11` { + var filename: String? + get() = definedExternally + set(value) = definedExternally + var scale: Number? + get() = definedExternally + set(value) = definedExternally + var format: String /* 'png' | 'svg' | 'jpeg' | 'webp' */ + var height: Number? + get() = definedExternally + set(value) = definedExternally + var width: Number? + get() = definedExternally + set(value) = definedExternally +} + +external interface Config { + var toImageButtonOptions: `T$11` + var staticPlot: Boolean + var editable: Boolean + var edits: EditsPartial + var autosizable: Boolean + var queueLength: Number + var fillFrame: Boolean + var frameMargins: Number + var scrollZoom: Boolean + var doubleClick: dynamic /* 'reset+autosize' | 'reset' | 'autosize' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var showTips: Boolean + var showAxisDragHandles: Boolean + var showAxisRangeEntryBoxes: Boolean + var showLink: Boolean + var sendData: Boolean + var linkText: String + var showSources: Boolean + var displayModeBar: dynamic /* 'hover' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var modeBarButtonsToRemove: Array<String /* 'lasso2d' | 'select2d' | 'sendDataToCloud' | 'zoom2d' | 'pan2d' | 'zoomIn2d' | 'zoomOut2d' | 'autoScale2d' | 'resetScale2d' | 'hoverClosestCartesian' | 'hoverCompareCartesian' | 'zoom3d' | 'pan3d' | 'orbitRotation' | 'tableRotation' | 'resetCameraDefault3d' | 'resetCameraLastSave3d' | 'hoverClosest3d' | 'zoomInGeo' | 'zoomOutGeo' | 'resetGeo' | 'hoverClosestGeo' | 'hoverClosestGl2d' | 'hoverClosestPie' | 'toggleHover' | 'toImage' | 'resetViews' | 'toggleSpikelines' */> + var modeBarButtonsToAdd: dynamic /* Array<String /* 'lasso2d' | 'select2d' | 'sendDataToCloud' | 'zoom2d' | 'pan2d' | 'zoomIn2d' | 'zoomOut2d' | 'autoScale2d' | 'resetScale2d' | 'hoverClosestCartesian' | 'hoverCompareCartesian' | 'zoom3d' | 'pan3d' | 'orbitRotation' | 'tableRotation' | 'resetCameraDefault3d' | 'resetCameraLastSave3d' | 'hoverClosest3d' | 'zoomInGeo' | 'zoomOutGeo' | 'resetGeo' | 'hoverClosestGeo' | 'hoverClosestGl2d' | 'hoverClosestPie' | 'toggleHover' | 'toImage' | 'resetViews' | 'toggleSpikelines' */> | Array<ModeBarButton> */ + get() = definedExternally + set(value) = definedExternally + var modeBarButtons: dynamic /* Array<Array<String /* 'lasso2d' | 'select2d' | 'sendDataToCloud' | 'zoom2d' | 'pan2d' | 'zoomIn2d' | 'zoomOut2d' | 'autoScale2d' | 'resetScale2d' | 'hoverClosestCartesian' | 'hoverCompareCartesian' | 'zoom3d' | 'pan3d' | 'orbitRotation' | 'tableRotation' | 'resetCameraDefault3d' | 'resetCameraLastSave3d' | 'hoverClosest3d' | 'zoomInGeo' | 'zoomOutGeo' | 'resetGeo' | 'hoverClosestGeo' | 'hoverClosestGl2d' | 'hoverClosestPie' | 'toggleHover' | 'toImage' | 'resetViews' | 'toggleSpikelines' */>> | Array<Array<ModeBarButton>> | Boolean */ + get() = definedExternally + set(value) = definedExternally + var displaylogo: Boolean + var plotGlPixelRatio: Number + var setBackground: () -> String + var topojsonURL: String + var mapboxAccessToken: String + var logging: dynamic /* Boolean | 0 | 1 | 2 */ + get() = definedExternally + set(value) = definedExternally + var globalTransforms: Array<Any> + var locale: String + var responsive: Boolean +} + +external interface ConfigPartial { + var toImageButtonOptions: `T$11`? + get() = definedExternally + set(value) = definedExternally + var staticPlot: Boolean? + get() = definedExternally + set(value) = definedExternally + var editable: Boolean? + get() = definedExternally + set(value) = definedExternally + var edits: Any? + get() = definedExternally + set(value) = definedExternally + var autosizable: Boolean? + get() = definedExternally + set(value) = definedExternally + var queueLength: Number? + get() = definedExternally + set(value) = definedExternally + var fillFrame: Boolean? + get() = definedExternally + set(value) = definedExternally + var frameMargins: Number? + get() = definedExternally + set(value) = definedExternally + var scrollZoom: Boolean? + get() = definedExternally + set(value) = definedExternally + var doubleClick: dynamic /* 'reset+autosize' | 'reset' | 'autosize' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var showTips: Boolean? + get() = definedExternally + set(value) = definedExternally + var showAxisDragHandles: Boolean? + get() = definedExternally + set(value) = definedExternally + var showAxisRangeEntryBoxes: Boolean? + get() = definedExternally + set(value) = definedExternally + var showLink: Boolean? + get() = definedExternally + set(value) = definedExternally + var sendData: Boolean? + get() = definedExternally + set(value) = definedExternally + var linkText: String? + get() = definedExternally + set(value) = definedExternally + var showSources: Boolean? + get() = definedExternally + set(value) = definedExternally + var displayModeBar: dynamic /* 'hover' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var modeBarButtonsToRemove: Array<String /* 'lasso2d' | 'select2d' | 'sendDataToCloud' | 'zoom2d' | 'pan2d' | 'zoomIn2d' | 'zoomOut2d' | 'autoScale2d' | 'resetScale2d' | 'hoverClosestCartesian' | 'hoverCompareCartesian' | 'zoom3d' | 'pan3d' | 'orbitRotation' | 'tableRotation' | 'resetCameraDefault3d' | 'resetCameraLastSave3d' | 'hoverClosest3d' | 'zoomInGeo' | 'zoomOutGeo' | 'resetGeo' | 'hoverClosestGeo' | 'hoverClosestGl2d' | 'hoverClosestPie' | 'toggleHover' | 'toImage' | 'resetViews' | 'toggleSpikelines' */>? + get() = definedExternally + set(value) = definedExternally + var modeBarButtonsToAdd: dynamic /* Array<String /* 'lasso2d' | 'select2d' | 'sendDataToCloud' | 'zoom2d' | 'pan2d' | 'zoomIn2d' | 'zoomOut2d' | 'autoScale2d' | 'resetScale2d' | 'hoverClosestCartesian' | 'hoverCompareCartesian' | 'zoom3d' | 'pan3d' | 'orbitRotation' | 'tableRotation' | 'resetCameraDefault3d' | 'resetCameraLastSave3d' | 'hoverClosest3d' | 'zoomInGeo' | 'zoomOutGeo' | 'resetGeo' | 'hoverClosestGeo' | 'hoverClosestGl2d' | 'hoverClosestPie' | 'toggleHover' | 'toImage' | 'resetViews' | 'toggleSpikelines' */> | Array<ModeBarButton> */ + get() = definedExternally + set(value) = definedExternally + var modeBarButtons: dynamic /* Array<Array<String /* 'lasso2d' | 'select2d' | 'sendDataToCloud' | 'zoom2d' | 'pan2d' | 'zoomIn2d' | 'zoomOut2d' | 'autoScale2d' | 'resetScale2d' | 'hoverClosestCartesian' | 'hoverCompareCartesian' | 'zoom3d' | 'pan3d' | 'orbitRotation' | 'tableRotation' | 'resetCameraDefault3d' | 'resetCameraLastSave3d' | 'hoverClosest3d' | 'zoomInGeo' | 'zoomOutGeo' | 'resetGeo' | 'hoverClosestGeo' | 'hoverClosestGl2d' | 'hoverClosestPie' | 'toggleHover' | 'toImage' | 'resetViews' | 'toggleSpikelines' */>> | Array<Array<ModeBarButton>> | Boolean */ + get() = definedExternally + set(value) = definedExternally + var displaylogo: Boolean? + get() = definedExternally + set(value) = definedExternally + var plotGlPixelRatio: Number? + get() = definedExternally + set(value) = definedExternally + var setBackground: (() -> String)? + get() = definedExternally + set(value) = definedExternally + var topojsonURL: String? + get() = definedExternally + set(value) = definedExternally + var mapboxAccessToken: String? + get() = definedExternally + set(value) = definedExternally + var logging: dynamic /* Boolean | 0 | 1 | 2 */ + get() = definedExternally + set(value) = definedExternally + var globalTransforms: Array<Any>? + get() = definedExternally + set(value) = definedExternally + var locale: String? + get() = definedExternally + set(value) = definedExternally + var responsive: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface RangeSlider { + var visible: Boolean + var thickness: Number + var range: dynamic /* JsTuple<dynamic, dynamic> */ + get() = definedExternally + set(value) = definedExternally + var borderwidth: Number + var bordercolor: String + var bgcolor: String +} + +external interface RangeSliderPartial { + var visible: Boolean? + get() = definedExternally + set(value) = definedExternally + var thickness: Number? + get() = definedExternally + set(value) = definedExternally + var range: dynamic /* JsTuple<dynamic, dynamic> */ + get() = definedExternally + set(value) = definedExternally + var borderwidth: Number? + get() = definedExternally + set(value) = definedExternally + var bordercolor: String? + get() = definedExternally + set(value) = definedExternally + var bgcolor: String? + get() = definedExternally + set(value) = definedExternally +} + +external interface RangeSelectorButton { + var step: String /* 'second' | 'minute' | 'hour' | 'day' | 'month' | 'year' | 'all' */ + var stepmode: String /* 'backward' | 'todate' */ + var count: Number + var label: String +} + +external interface RangeSelectorButtonPartial { + var step: String /* 'second' | 'minute' | 'hour' | 'day' | 'month' | 'year' | 'all' */ + var stepmode: String /* 'backward' | 'todate' */ + var count: Number? + get() = definedExternally + set(value) = definedExternally + var label: String? + get() = definedExternally + set(value) = definedExternally +} + +external interface RangeSelector : Label { + var buttons: Array<RangeSelectorButtonPartial> + var visible: Boolean + var x: Number + var xanchor: String /* 'auto' | 'left' | 'center' | 'right' */ + var y: Number + var yanchor: String /* 'auto' | 'top' | 'middle' | 'bottom' */ + var activecolor: String + var borderwidth: Number +} + +external interface RangeSelectorPartial : LabelPartial { + var buttons: Array<Partial<RangeSelectorButton>>? + get() = definedExternally + set(value) = definedExternally + var visible: Boolean? + get() = definedExternally + set(value) = definedExternally + var x: Number? + get() = definedExternally + set(value) = definedExternally + var xanchor: String /* 'auto' | 'left' | 'center' | 'right' */ + var y: Number? + get() = definedExternally + set(value) = definedExternally + var yanchor: String /* 'auto' | 'top' | 'middle' | 'bottom' */ + var activecolor: String? + get() = definedExternally + set(value) = definedExternally + var borderwidth: Number? + get() = definedExternally + set(value) = definedExternally +} + +external interface Camera { + var up: PointPartial + var center: PointPartial + var eye: PointPartial +} + +external interface CameraPartial { + var up: Any? + get() = definedExternally + set(value) = definedExternally + var center: Any? + get() = definedExternally + set(value) = definedExternally + var eye: Any? + get() = definedExternally + set(value) = definedExternally +} + +external interface Label { + var bgcolor: String + var bordercolor: String + var font: FontPartial +} + +external interface LabelPartial { + var bgcolor: String? + get() = definedExternally + set(value) = definedExternally + var bordercolor: String? + get() = definedExternally + set(value) = definedExternally + var font: FontPartial? + get() = definedExternally + set(value) = definedExternally +} + +external interface HoverLabel : Label { + var align: String /* "left" | "right" | "auto" */ + var namelength: Number +} + +external interface HoverLabelPartial : LabelPartial { + var align: String /* "left" | "right" | "auto" */ + var namelength: Number? + get() = definedExternally + set(value) = definedExternally +} + +external interface Annotations : Label { + var visible: Boolean + var text: String + var textangle: String + var width: Number + var height: Number + var opacity: Number + var align: String /* 'left' | 'center' | 'right' */ + var valign: String /* 'top' | 'middle' | 'bottom' */ + var borderpad: Number + var borderwidth: Number + var showarrow: Boolean + var arrowcolor: String + var arrowhead: Number + var startarrowhead: Number + var arrowside: String /* 'end' | 'start' */ + var arrowsize: Number + var startarrowsize: Number + var arrowwidth: Number + var standoff: Number + var startstandoff: Number + var ax: Number + var ay: Number + var axref: String /* 'pixel' */ + var ayref: String /* 'pixel' */ + var xref: String /* 'paper' | 'x' */ + var x: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var xanchor: String /* 'auto' | 'left' | 'center' | 'right' */ + var xshift: Number + var yref: String /* 'paper' | 'y' */ + var y: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var yanchor: String /* 'auto' | 'top' | 'middle' | 'bottom' */ + var yshift: Number + var clicktoshow: dynamic /* Boolean | 'onoff' | 'onout' */ + get() = definedExternally + set(value) = definedExternally + var xclick: Any + var yclick: Any + var hovertext: String + var hoverlabel: HoverLabelPartial + var captureevents: Boolean +} + +external interface AnnotationsPartial : LabelPartial { + var visible: Boolean? + get() = definedExternally + set(value) = definedExternally + var text: String? + get() = definedExternally + set(value) = definedExternally + var textangle: String? + get() = definedExternally + set(value) = definedExternally + var width: Number? + get() = definedExternally + set(value) = definedExternally + var height: Number? + get() = definedExternally + set(value) = definedExternally + var opacity: Number? + get() = definedExternally + set(value) = definedExternally + var align: String /* 'left' | 'center' | 'right' */ + var valign: String /* 'top' | 'middle' | 'bottom' */ + var borderpad: Number? + get() = definedExternally + set(value) = definedExternally + var borderwidth: Number? + get() = definedExternally + set(value) = definedExternally + var showarrow: Boolean? + get() = definedExternally + set(value) = definedExternally + var arrowcolor: String? + get() = definedExternally + set(value) = definedExternally + var arrowhead: Number? + get() = definedExternally + set(value) = definedExternally + var startarrowhead: Number? + get() = definedExternally + set(value) = definedExternally + var arrowside: String /* 'end' | 'start' */ + var arrowsize: Number? + get() = definedExternally + set(value) = definedExternally + var startarrowsize: Number? + get() = definedExternally + set(value) = definedExternally + var arrowwidth: Number? + get() = definedExternally + set(value) = definedExternally + var standoff: Number? + get() = definedExternally + set(value) = definedExternally + var startstandoff: Number? + get() = definedExternally + set(value) = definedExternally + var ax: Number? + get() = definedExternally + set(value) = definedExternally + var ay: Number? + get() = definedExternally + set(value) = definedExternally + var axref: String /* 'pixel' */ + var ayref: String /* 'pixel' */ + var xref: String /* 'paper' | 'x' */ + var x: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var xanchor: String /* 'auto' | 'left' | 'center' | 'right' */ + var xshift: Number? + get() = definedExternally + set(value) = definedExternally + var yref: String /* 'paper' | 'y' */ + var y: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var yanchor: String /* 'auto' | 'top' | 'middle' | 'bottom' */ + var yshift: Number? + get() = definedExternally + set(value) = definedExternally + var clicktoshow: dynamic /* Boolean | 'onoff' | 'onout' */ + get() = definedExternally + set(value) = definedExternally + var xclick: Any? + get() = definedExternally + set(value) = definedExternally + var yclick: Any? + get() = definedExternally + set(value) = definedExternally + var hovertext: String? + get() = definedExternally + set(value) = definedExternally + var hoverlabel: Any? + get() = definedExternally + set(value) = definedExternally + var captureevents: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface Image { + var visible: Boolean + var source: String + var layer: String /* 'above' | 'below' */ + var sizex: Number + var sizey: Number + var sizing: String /* 'fill' | 'contain' | 'stretch' */ + var opacity: Number + var x: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var y: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var xanchor: String /* 'left' | 'center' | 'right' */ + var yanchor: String /* 'top' | 'middle' | 'bottom' */ + var xref: String /* 'paper' | 'x' */ + var yref: String /* 'paper' | 'y' */ +} + +external interface ImagePartial { + var visible: Boolean? + get() = definedExternally + set(value) = definedExternally + var source: String? + get() = definedExternally + set(value) = definedExternally + var layer: String /* 'above' | 'below' */ + var sizex: Number? + get() = definedExternally + set(value) = definedExternally + var sizey: Number? + get() = definedExternally + set(value) = definedExternally + var sizing: String /* 'fill' | 'contain' | 'stretch' */ + var opacity: Number? + get() = definedExternally + set(value) = definedExternally + var x: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var y: dynamic /* Number | String */ + get() = definedExternally + set(value) = definedExternally + var xanchor: String /* 'left' | 'center' | 'right' */ + var yanchor: String /* 'top' | 'middle' | 'bottom' */ + var xref: String /* 'paper' | 'x' */ + var yref: String /* 'paper' | 'y' */ +} + +external interface Scene { + var bgcolor: String + var camera: CameraPartial + var domain: DomainPartial + var aspectmode: String /* 'auto' | 'cube' | 'data' | 'manual' */ + var aspectratio: PointPartial + var xaxis: SceneAxisPartial + var yaxis: SceneAxisPartial + var zaxis: SceneAxisPartial + var dragmode: dynamic /* 'orbit' | 'turntable' | 'zoom' | 'pan' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var hovermode: dynamic /* 'closest' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var annotations: dynamic /* AnnotationsPartial | Array<AnnotationsPartial> */ + get() = definedExternally + set(value) = definedExternally + var captureevents: Boolean +} + +external interface ScenePartial { + var bgcolor: String? + get() = definedExternally + set(value) = definedExternally + var camera: Any? + get() = definedExternally + set(value) = definedExternally + var domain: Any? + get() = definedExternally + set(value) = definedExternally + var aspectmode: String /* 'auto' | 'cube' | 'data' | 'manual' */ + var aspectratio: Any? + get() = definedExternally + set(value) = definedExternally + var xaxis: Any? + get() = definedExternally + set(value) = definedExternally + var yaxis: Any? + get() = definedExternally + set(value) = definedExternally + var zaxis: Any? + get() = definedExternally + set(value) = definedExternally + var dragmode: dynamic /* 'orbit' | 'turntable' | 'zoom' | 'pan' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var hovermode: dynamic /* 'closest' | Boolean */ + get() = definedExternally + set(value) = definedExternally + var annotations: dynamic /* Partial<Annotations> | Array<Partial<Annotations>> */ + get() = definedExternally + set(value) = definedExternally + var captureevents: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface Domain { + var x: Array<Number> + var y: Array<Number> + var row: Number + var column: Number +} + +external interface DomainPartial { + var x: Array<Number>? + get() = definedExternally + set(value) = definedExternally + var y: Array<Number>? + get() = definedExternally + set(value) = definedExternally + var row: Number? + get() = definedExternally + set(value) = definedExternally + var column: Number? + get() = definedExternally + set(value) = definedExternally +} + +external interface Frame { + var group: String + var name: String + var traces: Array<Number> + var baseframe: String + var data: Array<Data> + var layout: LayoutPartial +} + +external interface FramePartial { + var group: String? + get() = definedExternally + set(value) = definedExternally + var name: String? + get() = definedExternally + set(value) = definedExternally + var traces: Array<Number>? + get() = definedExternally + set(value) = definedExternally + var baseframe: String? + get() = definedExternally + set(value) = definedExternally + var data: Array<Data>? + get() = definedExternally + set(value) = definedExternally + var layout: Any? + get() = definedExternally + set(value) = definedExternally +} + +external interface Transition { + var duration: Number + var easing: String /* 'linear' | 'quad' | 'cubic' | 'sin' | 'exp' | 'circle' | 'elastic' | 'back' | 'bounce' | 'linear-in' | 'quad-in' | 'cubic-in' | 'sin-in' | 'exp-in' | 'circle-in' | 'elastic-in' | 'back-in' | 'bounce-in' | 'linear-out' | 'quad-out' | 'cubic-out' | 'sin-out' | 'exp-out' | 'circle-out' | 'elastic-out' | 'back-out' | 'bounce-out' | 'linear-in-out' | 'quad-in-out' | 'cubic-in-out' | 'sin-in-out' | 'exp-in-out' | 'circle-in-out' | 'elastic-in-out' | 'back-in-out' | 'bounce-in-out' */ + var ordering: String /* 'layout first' | 'traces first' */ +} + +external interface SliderStep { + var visible: Boolean + var method: String /* 'animate' | 'relayout' | 'restyle' | 'skip' | 'update' */ + var args: Array<Any> + var label: String + var value: String + var execute: Boolean +} + +external interface SliderStepPartial { + var visible: Boolean? + get() = definedExternally + set(value) = definedExternally + var method: String /* 'animate' | 'relayout' | 'restyle' | 'skip' | 'update' */ + var args: Array<Any>? + get() = definedExternally + set(value) = definedExternally + var label: String? + get() = definedExternally + set(value) = definedExternally + var value: String? + get() = definedExternally + set(value) = definedExternally + var execute: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +external interface Padding { + var t: Number + var r: Number + var b: Number + var l: Number + var editType: String /* 'arraydraw' */ +} + +external interface PaddingPartial { + var t: Number? + get() = definedExternally + set(value) = definedExternally + var r: Number? + get() = definedExternally + set(value) = definedExternally + var b: Number? + get() = definedExternally + set(value) = definedExternally + var l: Number? + get() = definedExternally + set(value) = definedExternally + var editType: String /* 'arraydraw' */ +} + +external interface `T$12` { + var visible: Boolean + var xanchor: String /* 'left' | 'center' | 'right' */ + var offset: Number + var prefix: String + var suffix: String + var font: FontPartial +} + +external interface Slider { + var visible: Boolean + var active: Number + var steps: Array<SliderStepPartial> + var lenmode: String /* 'fraction' | 'pixels' */ + var len: Number + var x: Number + var y: Number + var pad: PaddingPartial + var xanchor: String /* 'auto' | 'left' | 'center' | 'right' */ + var yanchor: String /* 'auto' | 'top' | 'middle' | 'bottom' */ + var transition: Transition + var currentvalue: `T$12` + var font: Font + var activebgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var bordercolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var borderwidth: Number + var ticklen: Number + var tickcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var tickwidth: Number + var minorticklen: Number +} + +external interface SliderPartial { + var visible: Boolean? + get() = definedExternally + set(value) = definedExternally + var active: Number? + get() = definedExternally + set(value) = definedExternally + var steps: Array<Partial<SliderStep>>? + get() = definedExternally + set(value) = definedExternally + var lenmode: String /* 'fraction' | 'pixels' */ + var len: Number? + get() = definedExternally + set(value) = definedExternally + var x: Number? + get() = definedExternally + set(value) = definedExternally + var y: Number? + get() = definedExternally + set(value) = definedExternally + var pad: Any? + get() = definedExternally + set(value) = definedExternally + var xanchor: String /* 'auto' | 'left' | 'center' | 'right' */ + var yanchor: String /* 'auto' | 'top' | 'middle' | 'bottom' */ + var transition: Transition? + get() = definedExternally + set(value) = definedExternally + var currentvalue: `T$12`? + get() = definedExternally + set(value) = definedExternally + var font: Font? + get() = definedExternally + set(value) = definedExternally + var activebgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var bgcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var bordercolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var borderwidth: Number? + get() = definedExternally + set(value) = definedExternally + var ticklen: Number? + get() = definedExternally + set(value) = definedExternally + var tickcolor: dynamic /* String | Number | Array<dynamic /* String | Number | Nothing? | Nothing? */> | Array<Array<dynamic /* String | Number | Nothing? | Nothing? */>> */ + get() = definedExternally + set(value) = definedExternally + var tickwidth: Number? + get() = definedExternally + set(value) = definedExternally + var minorticklen: Number? + get() = definedExternally + set(value) = definedExternally +} + +external fun restyle(root: String, aobj: Data): Promise<PlotlyHTMLElement> + +external fun restyle(root: HTMLElement, aobj: Data): Promise<PlotlyHTMLElement> + +external fun update(root: String, traceUpdate: Data, layoutUpdate: LayoutPartial): Promise<PlotlyHTMLElement> + +external fun update(root: HTMLElement, traceUpdate: Data, layoutUpdate: LayoutPartial): Promise<PlotlyHTMLElement> + +external fun addTraces(root: String, traces: Data): Promise<PlotlyHTMLElement> + +external fun addTraces(root: String, traces: Array<Data>): Promise<PlotlyHTMLElement> + +external fun addTraces(root: HTMLElement, traces: Data): Promise<PlotlyHTMLElement> + +external fun addTraces(root: HTMLElement, traces: Array<Data>): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: String, currentIndices: Array<Number>): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: String, currentIndices: Number): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: HTMLElement, currentIndices: Array<Number>): Promise<PlotlyHTMLElement> + +external fun moveTraces(root: HTMLElement, currentIndices: Number): Promise<PlotlyHTMLElement> \ No newline at end of file diff --git a/plotly/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/bootstrapHeaders.kt b/plotly/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/bootstrapHeaders.kt new file mode 100644 index 00000000..db098a5b --- /dev/null +++ b/plotly/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/bootstrapHeaders.kt @@ -0,0 +1,52 @@ +package space.kscience.plotly + +import kotlinx.html.link +import kotlinx.html.script + + +//public fun localBootstrap(basePath: Path) = HtmlFragment { +// script { +// type = "text/javascript" +// src = checkOrStoreFile( +// basePath, +// Path.of(assetsDirectory + jQueryPath), +// jQueryPath +// ).toString() +// } +// script { +// type = "text/javascript" +// src = checkOrStoreFile( +// basePath, +// Path.of(assetsDirectory + bootstrapJsPath), +// bootstrapJsPath +// ).toString() +// } +// link { +// rel = "stylesheet" +// href = checkOrStoreFile( +// basePath, +// Path.of(assetsDirectory + bootstrapCssPath), +// bootstrapCssPath +// ).toString() +// } +//} + +public val cdnBootstrap: PlotlyHtmlFragment = PlotlyHtmlFragment { + script { + src = "https://code.jquery.com/jquery-3.5.1.slim.min.js" + integrity = "sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" + attributes["crossorigin"] = "anonymous" + } + script { + src = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.bundle.min.js" + integrity = "sha384-1CmrxMRARb6aLqgBO7yyAxTOQE2AKb9GfXnEo760AUcUmFx3ibVJJAzGytlQcNXd" + attributes["crossorigin"] = "anonymous" + } + link { + rel = "stylesheet" + href = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" + attributes["integrity"] = "sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" + attributes["crossorigin"] = "anonymous" + } +} + diff --git a/plotly/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/fileExport.kt b/plotly/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/fileExport.kt new file mode 100644 index 00000000..0b0741b7 --- /dev/null +++ b/plotly/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/fileExport.kt @@ -0,0 +1,145 @@ +package space.kscience.plotly + +import kotlinx.html.FlowContent +import java.awt.Desktop +import java.nio.file.Files +import java.nio.file.Path +import javax.swing.JFileChooser +import javax.swing.filechooser.FileNameExtensionFilter + + +internal const val assetsDirectory = "assets" + +/** + * The location of resources for plot. + */ +public enum class ResourceLocation { + /** + * Use cdn or other remote source for assets + */ + REMOTE, + + /** + * Store assets in a sibling folder `plotly-assets` or in a system-wide folder if this is a default temporary file + */ + LOCAL, + + /** + * Store assets in a system-window `~/.plotly/plotly-assets` folder + */ + SYSTEM, + + /** + * Embed the asset into the html. Could produce very large files. + */ + EMBED +} + +/** + * Create a standalone html with the plot + * @param path the reference to html file. If null, create a temporary file + * @param resourceLocation specifies where to store resources for page display + * @param show if true, start the browser after file is created + * @param config represents plotly frame configuration + */ +public fun Plot.makeFile( + path: Path? = null, + show: Boolean = true, + resourceLocation: ResourceLocation = ResourceLocation.LOCAL, + config: PlotlyConfig = PlotlyConfig(), +) { + val actualFile = path ?: Files.createTempFile("tempPlot", ".html") + Files.createDirectories(actualFile.parent) + Files.writeString(actualFile, toHTML(inferPlotlyHeader(path, resourceLocation), config = config)) + if (show) { + Desktop.getDesktop().browse(actualFile.toFile().toURI()) + } +} + +/** + * The same as [Plot.makeFile]. + */ +public fun PlotlyFragment.makeFile( + path: Path? = null, + show: Boolean = true, + title: String = "Plotly.kt", + resourceLocation: ResourceLocation = ResourceLocation.LOCAL, + additionalHeaders: List<PlotlyHtmlFragment> = emptyList(), +) { + toPage( + title = title, + headers = (additionalHeaders + inferPlotlyHeader(path, resourceLocation)).toTypedArray() + ).makeFile(path, show) +} + + +/** + * Export a page html to a file. + */ +public fun PlotlyPage.makeFile(path: Path? = null, show: Boolean = true) { + val actualFile = path ?: Files.createTempFile("tempPlot", ".html") + Files.createDirectories(actualFile.parent) + Files.writeString(actualFile, render()) + if (show) { + Desktop.getDesktop().browse(actualFile.toFile().toURI()) + } +} + +public fun Plotly.display(pageBuilder: FlowContent.(renderer: PlotlyRenderer) -> Unit): Unit = + fragment(pageBuilder).makeFile(null, true) + +/** + * Select a file to save plot to using Swing form. + */ +@UnstablePlotlyAPI +public fun selectFile(filter: FileNameExtensionFilter? = null): Path? { + val fileChooser = JFileChooser() + fileChooser.dialogTitle = "Specify a file to save" + if (filter != null) { + fileChooser.fileFilter = filter + } + + val userSelection = fileChooser.showSaveDialog(null) + + return if (userSelection == JFileChooser.APPROVE_OPTION) { + val fileToSave = fileChooser.selectedFile + fileToSave.toPath() + } else { + null + } +} + +/** + * Output format for Orca export + */ +public enum class OrcaFormat { + png, jpeg, webp, svg, pdf +} + +/** + * Use external [plotly-orca] (https://github.com/plotly/orca) tool to export static image. + * The tool must be installed externally (for example via conda) and usage patterns could differ for different systems. + */ +@UnstablePlotlyAPI +public fun Plot.export(path: Path, format: OrcaFormat = OrcaFormat.svg) { + val tempFile = Files.createTempFile("plotly-orca-export", ".json") + Files.writeString(tempFile, toJsonString()) + + val command = if (System.getProperty("os.name").contains("Windows")) { + "powershell" + } else { + "bash" + } + + val process = ProcessBuilder( + command, "orca", "graph", tempFile.toAbsolutePath().toString(), + "-f", format.toString(), + "-d", path.parent.toString(), + "-o", path.fileName.toString(), + "--verbose" + ).redirectErrorStream(true).start() + process.outputStream.close() + val output = process.inputStream.bufferedReader().use { it.readText() } + println(output) + println("Orca finished with code: ${process.waitFor()}") +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/plotlyHeaders.kt b/plotly/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/plotlyHeaders.kt new file mode 100644 index 00000000..73abd52f --- /dev/null +++ b/plotly/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/plotlyHeaders.kt @@ -0,0 +1,119 @@ +package space.kscience.plotly + +import kotlinx.html.link +import kotlinx.html.script +import kotlinx.html.unsafe +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.StandardOpenOption + + +internal const val PLOTLY_SCRIPT_PATH = "/js/plotly.min.js" +//const val PLOTLY_PROMISE_NAME = "promiseOfPlotly" +/** + * Check if the asset exists in given local location and put it there if it does not + */ +internal fun checkOrStoreFile(basePath: Path, filePath: Path, resource: String): Path { + val fullPath = basePath.resolveSibling(filePath).toAbsolutePath() + + if (Files.exists(fullPath)) { + //TODO checksum + } else { + //TODO add logging + + val bytes = PlotlyHtmlFragment::class.java.getResourceAsStream(resource)!!.readAllBytes() + Files.createDirectories(fullPath.parent) + Files.write(fullPath, bytes, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE) + } + + return if (basePath.isAbsolute && fullPath.startsWith(basePath)) { + basePath.relativize(fullPath) + } else { + filePath + } +} + +/** + * A header that automatically copies relevant scripts to given path + */ +public fun localScriptHeader( + basePath: Path, + scriptPath: Path, + resource: String, +): PlotlyHtmlFragment = PlotlyHtmlFragment { + val relativePath = checkOrStoreFile(basePath, scriptPath, resource) + script { + type = "text/javascript" + src = relativePath.toString() + attributes["onload"] = "console.log('Script successfully loaded from $relativePath')" + attributes["onerror"] = "console.log('Failed to load script from $relativePath')" + } +} + +public fun localCssHeader( + basePath: Path, + cssPath: Path, + resource: String, +): PlotlyHtmlFragment = PlotlyHtmlFragment { + val relativePath = checkOrStoreFile(basePath, cssPath, resource) + link { + rel = "stylesheet" + href = relativePath.toString() + } +} + + +internal fun localPlotlyHeader( + path: Path, + relativeScriptPath: String = "$assetsDirectory$PLOTLY_SCRIPT_PATH" +) = PlotlyHtmlFragment { + val relativePath = checkOrStoreFile(path, Path.of(relativeScriptPath), PLOTLY_SCRIPT_PATH) + script { + type = "text/javascript" + src = relativePath.toString() + } +} + + +/** + * A system-wide plotly store location + */ +internal val systemPlotlyHeader = PlotlyHtmlFragment { + val relativePath = checkOrStoreFile( + Path.of("."), + Path.of(System.getProperty("user.home")).resolve(".plotly/$assetsDirectory$PLOTLY_SCRIPT_PATH"), + PLOTLY_SCRIPT_PATH + ) + script { + type = "text/javascript" + src = relativePath.toString() + } +} + + +/** + * embedded plotly script + */ +internal val embededPlotlyHeader = PlotlyHtmlFragment { + script { + unsafe { + val bytes = PlotlyHtmlFragment::class.java.getResourceAsStream(PLOTLY_SCRIPT_PATH)!!.readAllBytes() + +bytes.toString(Charsets.UTF_8) + } + } +} + + +internal fun inferPlotlyHeader( + target: Path?, + resourceLocation: ResourceLocation +): PlotlyHtmlFragment = when (resourceLocation) { + ResourceLocation.REMOTE -> cdnPlotlyHeader + ResourceLocation.LOCAL -> if (target != null) { + localPlotlyHeader(target) + } else { + systemPlotlyHeader + } + ResourceLocation.SYSTEM -> systemPlotlyHeader + ResourceLocation.EMBED -> embededPlotlyHeader +} diff --git a/plotly/plotlykt-core/src/jvmTest/kotlin/space/kscience/plotly/PlotSerializationTest.kt b/plotly/plotlykt-core/src/jvmTest/kotlin/space/kscience/plotly/PlotSerializationTest.kt new file mode 100644 index 00000000..b2e7c8e3 --- /dev/null +++ b/plotly/plotlykt-core/src/jvmTest/kotlin/space/kscience/plotly/PlotSerializationTest.kt @@ -0,0 +1,44 @@ +package space.kscience.plotly + +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.jsonObject +import org.junit.jupiter.api.Test +import space.kscience.dataforge.meta.ListValue +import space.kscience.dataforge.meta.ObservableMutableMeta +import space.kscience.plotly.models.ShapeType +import space.kscience.plotly.models.TraceType +import kotlin.test.assertEquals +import kotlin.test.assertTrue + + +class PlotSerializationTest { + @Test + fun deserialization() { + val meta = ObservableMutableMeta { + "data" put { + "x" put ListValue(1, 2, 3) + "y" put ListValue(5, 6, 7) + "type" put "scatter" + } + } + + val plot = Plot(meta) + assertEquals(1, plot.data.size) + assertEquals(TraceType.scatter, plot.data[0].type) + assertEquals(1.0, plot.data[0].x.doubles[0]) + } + + @Test + fun shapeSerialization(){ + val plot = Plotly.plot { + shape { + type = ShapeType.rect + } + } + + val json = plot.toJson() + println(json.toString()) + val shapes = json["layout"]?.jsonObject?.get("shapes") + assertTrue { shapes is JsonArray } + } +} \ No newline at end of file diff --git a/plotly/plotlykt-core/src/nativeMain/kotlin/space/kscience/plotly/makeFile.kt b/plotly/plotlykt-core/src/nativeMain/kotlin/space/kscience/plotly/makeFile.kt new file mode 100644 index 00000000..37363b7a --- /dev/null +++ b/plotly/plotlykt-core/src/nativeMain/kotlin/space/kscience/plotly/makeFile.kt @@ -0,0 +1,46 @@ +package space.kscience.plotly + +import okio.FileSystem +import okio.Path +import okio.Path.Companion.toPath + +/** + * Create a standalone html with the plot + * @param path the reference to html file. If null, create a temporary file + * @param show if true, start the browser after file is created + * @param config represents plotly frame configuration + */ +@UnstablePlotlyAPI +public fun Plot.makeFile( + path: Path, + config: PlotlyConfig = PlotlyConfig(), +) { + FileSystem.SYSTEM.write(path, true) { + writeUtf8(toHTML(cdnPlotlyHeader, config = config)) + } +} + +@UnstablePlotlyAPI +public fun Plot.makeFile( + path: String, + config: PlotlyConfig = PlotlyConfig(), +) { + makeFile(path.toPath(), config) +} + +/** + * Export a page html to a file. + */ +@UnstablePlotlyAPI +public fun PlotlyPage.makeFile(path: Path) { + FileSystem.SYSTEM.write(path, true) { + writeUtf8(render()) + } +} + +@UnstablePlotlyAPI +public fun PlotlyPage.makeFile( + path: String, +) { + makeFile(path.toPath()) +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/README.md b/plotly/plotlykt-geo/README.md new file mode 100644 index 00000000..f15f5f2a --- /dev/null +++ b/plotly/plotlykt-geo/README.md @@ -0,0 +1,21 @@ +# Module plotlykt-geo + + + +## Usage + +## Artifact: + +The Maven coordinates of this project are `space.kscience:plotlykt-geo:0.7.1`. + +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:plotlykt-geo:0.7.1") +} +``` diff --git a/plotly/plotlykt-geo/build.gradle.kts b/plotly/plotlykt-geo/build.gradle.kts new file mode 100644 index 00000000..5cad496a --- /dev/null +++ b/plotly/plotlykt-geo/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + id("space.kscience.gradle.mpp") + `maven-publish` +} + +kscience{ + jvm() + js() + native() + wasm() + dependencies { + api(projects.plotly.plotlyktCore) + } +} + +readme{ + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/Choropleth.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/Choropleth.kt new file mode 100644 index 00000000..f604d80a --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/Choropleth.kt @@ -0,0 +1,31 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.plotly.Plot +import space.kscience.plotly.models.TraceType +import kotlin.js.JsName + +public enum class LocationMode{ + @JsName("iso3") + `ISO-3`, + @JsName("usa") + `USA-states`, + @JsName("country") + `country names`, + @JsName("geojson") + `geojson-id` +} + +public class Choropleth : GeoTrace() { + init { + type = TraceType.choropleth + } + + public companion object : SchemeSpec<Choropleth>(::Choropleth) +} + +public inline fun Plot.choropleth(block: Choropleth.() -> Unit): Choropleth { + val trace = Choropleth(block) + traces(trace) + return trace +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/ChoroplethMapBox.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/ChoroplethMapBox.kt new file mode 100644 index 00000000..ffe7d7b8 --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/ChoroplethMapBox.kt @@ -0,0 +1,19 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.plotly.Plot +import space.kscience.plotly.models.TraceType + +public class ChoroplethMapBox : GeoTrace() { + init { + type = TraceType.choroplethmapbox + } + + public companion object : SchemeSpec<ChoroplethMapBox>(::ChoroplethMapBox) +} + +public inline fun Plot.choroplethMapBox(block: ChoroplethMapBox.() -> Unit): ChoroplethMapBox { + val trace = ChoroplethMapBox(block) + traces(trace) + return trace +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/Geo.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/Geo.kt new file mode 100644 index 00000000..b8585f29 --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/Geo.kt @@ -0,0 +1,71 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.models.Color +import space.kscience.plotly.models.Layout +import space.kscience.plotly.models.color +import kotlin.js.JsName + +public enum class GeoScope{ + africa, + asia, + europe, + @JsName("northAmerica") + `north america`, + @JsName("southAmerica") + `south america`, + usa, + world +} + + +public class Geo : Scheme() { + public val bgcolor: Color by color() + public var center: MapCoordinates by scheme(MapCoordinates) + + public val coastlinecolor: Color by color() + public var coastlinewidth: Number by number(1) + + public val countrycolor: Color by color() + public var countrywidth: Number by number(1) + + public var fitbounds: Value? by value() + + public val framecolor: Color by color() + public var framewidth: Number by number(1) + + public val lakecolor: Color by color() + + public val landcolor: Color by color() + + public val oceancolor: Color by color() + + public val rivercolor: Color by color() + public var riverwidth: Number by number(1) + + public val subunitcolor: Color by color() + public var subunitwidth: Number by number(1) + + + public var showcoastlines: Boolean? by boolean() + public var showcountries: Boolean? by boolean() + public var showframe: Boolean? by boolean() + public var showlakes: Boolean? by boolean() + public var showland: Boolean? by boolean() + public var showocean: Boolean? by boolean() + + public var lataxis: MapAxis by scheme(MapAxis) + public var lonaxis: MapAxis by scheme(MapAxis) + + public var projection: GeoProjection by scheme(GeoProjection) + + public var scope: GeoScope by enum(GeoScope.world) + + public companion object : SchemeSpec<Geo>(::Geo) +} + +public var Layout.geo: Geo + get() = Geo.write(meta.getOrCreate("geo")) + set(value){ + meta["geo"] = value.meta + } \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/GeoMapBox.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/GeoMapBox.kt new file mode 100644 index 00000000..d0a22d4d --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/GeoMapBox.kt @@ -0,0 +1,70 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.Plot +import space.kscience.plotly.models.Layout + +public class GeoMapBox : Scheme() { + /** + * Sets the mapbox access token to be used for this mapbox map. Alternatively, the mapbox access token can be set + * in the configuration options under `mapboxAccessToken`. Note that accessToken are only required when `style` + * (e.g with values : basic, streets, outdoors, light, dark, satellite, satellite-streets ) and/or a layout layer + * references the Mapbox server. + */ + public var accesstoken: String? by string() + + /** + * Sets the bearing angle of the map in degrees counter-clockwise from North (mapbox.bearing). + */ + public var bearing: Number by number(0) + + /** + * Sets the pitch angle of the map (in degrees, where "0" means perpendicular to the surface of the map) (mapbox.pitch). + */ + public var pitch: Number by number(0) + + public var center: MapCoordinates by scheme(MapCoordinates) + + //TODO domain + + //TODO layers + + /** + * Defines the map layers that are rendered by default below the trace layers defined in `data`, which are + * themselves by default rendered below the layers defined in `layout.mapbox.layers`. These layers can be defined + * either explicitly as a Mapbox Style object which can contain multiple layer definitions that load data from any + * public or private Tile Map Service (TMS or XYZ) or Web Map Service (WMS) or implicitly by using one of the + * built-in style objects which use WMSes which do not require any access tokens, or by using a default Mapbox + * style or custom Mapbox style URL, both of which require a Mapbox access token Note that Mapbox access token can + * be set in the `accesstoken` attribute or in the `mapboxAccessToken` config option. Mapbox Style objects are of + * the form described in the Mapbox GL JS documentation available at https://docs.mapbox.com/mapbox-gl-js/style-spec + * The built-in plotly.js styles objects are: carto-darkmatter, carto-positron, open-street-map, stamen-terrain, + * stamen-toner, stamen-watercolor, white-bg The built-in Mapbox styles are: basic, streets, outdoors, light, dark, + * satellite, satellite-streets Mapbox style URLs are of the form: mapbox://mapbox.mapbox-<name>-<version> + */ + public var style: Value? by value() + + /** + * Sets the zoom level of the map (mapbox.zoom). + */ + public var zoom: Number by number(1.0) + + public companion object : SchemeSpec<GeoMapBox>(::GeoMapBox) +} + +public fun GeoMapBox.useOpenStreetMap() { + style = "open-street-map".asValue() +} + +public var Layout.mapbox: GeoMapBox + get() = GeoMapBox.write(meta.getOrCreate("mapbox")) + set(value) { + meta["mapbox"] = value.meta + } + +public fun Plot.openStreetMap(block: GeoMapBox.() -> Unit) { + layout.mapbox { + useOpenStreetMap() + block() + } +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/GeoProjection.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/GeoProjection.kt new file mode 100644 index 00000000..cd3f53e1 --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/GeoProjection.kt @@ -0,0 +1,28 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.* +import space.kscience.plotly.numberGreaterThan + +public class GeoProjection : Scheme() { + /** + * For satellite projection type only. Sets the distance from the center of the sphere to + * the point of view as a proportion of the sphere’s radius. + */ + public var distance: Number by numberGreaterThan(1.001, default = 2.0) + public var rotation: MapCoordinatesWithRotation by scheme(MapCoordinatesWithRotation) + + /** + * Zooms in or out on the map view. A scale of "1" corresponds + * to the largest zoom level that fits the map's lon and lat ranges. + */ + public var scale: Number by number(1.0) + + /** + * For satellite projection type only. Sets the tilt angle of perspective projection. + */ + public var tilt: Number by number(0.0) + + public var type: String? by string() + + public companion object : SchemeSpec<GeoProjection>(::GeoProjection) +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/GeoTrace.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/GeoTrace.kt new file mode 100644 index 00000000..313fdc03 --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/GeoTrace.kt @@ -0,0 +1,56 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.asName +import space.kscience.plotly.models.Trace +import space.kscience.plotly.models.TraceValues +import space.kscience.plotly.models.geo.json.GeoJsonFeatureCollection + +public abstract class GeoTrace : Trace() { + + public val locations: TraceValues by axis + + /** + * + * Sets optional GeoJSON data associated with this trace. If not given, the features on the base map are used. + * It can be set as a valid GeoJSON object or as a URL string. Note that we only accept GeoJSONs of type + * "FeatureCollection" or "Feature" with geometries of type "Polygon" or "MultiPolygon". + * TODO replace by typed wrapper + */ + public var geojson: Meta? by node() + + /** + * Set GeoJson from in-memory Json + */ + public fun geoJsonFeatures(collections: GeoJsonFeatureCollection) { + geojson = collections.json.toMeta() + } + + /** + * An url to geojson + */ + public var geojsonUrl: String? by string(key = "geojson".asName()) + + /** + * Sets the key in GeoJSON features which is used as id to match the items included in the `locations` array. + * Only has an effect when `geojson` is set. Support nested property, for example "properties.name". + */ + public var featureidkey: String by string("id") + + /** + * Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined + * by `colorscale`. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will + * be chosen according to whether numbers in the `color` array are all positive, all negative or mixed. + */ + public var autocolorscale: Boolean by boolean(true) + + /** + * Sets a reference between this trace's geospatial coordinates and a geographic map. If "geo" (the default value), + * the geospatial coordinates refer to `layout.geo`. If "geo2", the geospatial coordinates refer to `layout.geo2`, + * and so on. + */ + public var geo: String? by string() + + public var locationmode: LocationMode by enum(LocationMode.`ISO-3`) + +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/MapAxis.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/MapAxis.kt new file mode 100644 index 00000000..30fd2842 --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/MapAxis.kt @@ -0,0 +1,47 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.meta.set +import space.kscience.plotly.models.Color +import space.kscience.plotly.models.color + + +public class MapAxis : Scheme() { + /** + * Sets the graticule's longitude/latitude tick step. + */ + public var dtick: Number? by number() + + /** + * Sets the graticule's stroke color. + */ + public val gridcolor: Color by color() + + /** + * Sets the graticule's stroke width (in px). + */ + public var gridwidth: Number by number(1) + + /** + * Sets the range of this axis (in degrees), sets the map's clipped coordinates. + */ + public fun range(from: Value, to: Value) { + meta["range"] = ListValue(listOf(from, to)) + } + + public fun range(value: ClosedFloatingPointRange<Double>) { + range(value.start.asValue(), value.endInclusive.asValue()) + } + + /** + * Sets whether graticule are shown on the map. + */ + public var showgrid: Boolean? by boolean() + + /** + * Sets the graticule's starting tick longitude/latitude. + */ + public var tick0: Number by number(0) + + public companion object : SchemeSpec<MapAxis>(::MapAxis) +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/MapCoordinates.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/MapCoordinates.kt new file mode 100644 index 00000000..e6651979 --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/MapCoordinates.kt @@ -0,0 +1,18 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.Scheme +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.dataforge.meta.number + +public open class MapCoordinates : Scheme() { + public var lat: Number? by number() + public var lon: Number? by number() + + public companion object : SchemeSpec<MapCoordinates>(::MapCoordinates) +} + +public class MapCoordinatesWithRotation : MapCoordinates() { + public var roll: Number? by number() + public companion object : SchemeSpec<MapCoordinatesWithRotation>(::MapCoordinatesWithRotation) +} + diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/ScatterGeo.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/ScatterGeo.kt new file mode 100644 index 00000000..8f50cbb2 --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/ScatterGeo.kt @@ -0,0 +1,24 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.plotly.Plot +import space.kscience.plotly.models.TraceType +import space.kscience.plotly.models.TraceValues + +public class ScatterGeo : GeoTrace() { + init { + type = TraceType.scattergeo + } + + public val ids: TraceValues by axis + public val lat: TraceValues by axis + public val lon: TraceValues by axis + + public companion object : SchemeSpec<ScatterGeo>(::ScatterGeo) +} + +public inline fun Plot.scattergeo(block: ScatterGeo.() -> Unit): ScatterGeo { + val trace = ScatterGeo(block) + traces(trace) + return trace +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/ScatterMapBox.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/ScatterMapBox.kt new file mode 100644 index 00000000..2f7ef448 --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/ScatterMapBox.kt @@ -0,0 +1,24 @@ +package space.kscience.plotly.models.geo + +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.plotly.Plot +import space.kscience.plotly.models.TraceType +import space.kscience.plotly.models.TraceValues + +public class ScatterMapBox : GeoTrace() { + init { + type = TraceType.scattermapbox + } + + public val ids: TraceValues by axis + public val lat: TraceValues by axis + public val lon: TraceValues by axis + + public companion object : SchemeSpec<ScatterMapBox>(::ScatterMapBox) +} + +public inline fun Plot.scattermapbox(block: ScatterMapBox.() -> Unit): ScatterMapBox { + val trace = ScatterMapBox(block) + traces(trace) + return trace +} \ No newline at end of file diff --git a/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/json/GeoJson.kt b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/json/GeoJson.kt new file mode 100644 index 00000000..0e89efd7 --- /dev/null +++ b/plotly/plotlykt-geo/src/commonMain/kotlin/space/kscience/plotly/models/geo/json/GeoJson.kt @@ -0,0 +1,53 @@ +package space.kscience.plotly.models.geo.json + +import kotlinx.serialization.json.* + +/** + * An utility class to work with GeoJson (https://geojson.org/) + */ +public open class GeoJson(public val json: JsonObject) { + public val type: String get() = json["type"]?.jsonPrimitive?.content ?: error("Not a GeoJson") +} + +public class GeoJsonFeature(json: JsonObject) : GeoJson(json) { + init { + require(type == "Feature") { "Not a GeoJson Feature" } + } + + public val id: JsonPrimitive? get() = json["id"]?.jsonPrimitive + + public val properties: JsonObject? get() = json["properties"]?.jsonObject + + public fun getProperty(propertyName: String): JsonPrimitive? = properties?.get(propertyName)?.jsonPrimitive + + public fun getString(propertyName: String): String? = getProperty(propertyName)?.contentOrNull +} + +public class GeoJsonFeatureCollection(json: JsonObject) : GeoJson(json), Iterable<GeoJsonFeature> { + init { + require(type == "FeatureCollection") { "Not a GeoJson FeatureCollection" } + } + + public val features: List<GeoJsonFeature> + get() = json["features"]!!.jsonArray.map { + GeoJsonFeature(it.jsonObject) + } + + override fun iterator(): Iterator<GeoJsonFeature> = features.iterator() + + public companion object { + public fun parse(string: String): GeoJsonFeatureCollection = GeoJsonFeatureCollection( + Json.parseToJsonElement(string).jsonObject + ) + } +} + +/** + * Combine a collection of features to a new [GeoJsonFeatureCollection] + */ +public fun Collection<GeoJsonFeature>.combine(): GeoJsonFeatureCollection = GeoJsonFeatureCollection( + buildJsonObject { + put("type", "FeatureCollection") + put("features", JsonArray(this@combine.map { it.json })) + } +) \ No newline at end of file diff --git a/plotly/plotlykt-jupyter/README.md b/plotly/plotlykt-jupyter/README.md new file mode 100644 index 00000000..d27b29a7 --- /dev/null +++ b/plotly/plotlykt-jupyter/README.md @@ -0,0 +1,21 @@ +# Module plotlykt-jupyter + + + +## Usage + +## Artifact: + +The Maven coordinates of this project are `space.kscience:plotlykt-jupyter:0.7.1`. + +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:plotlykt-jupyter:0.7.1") +} +``` diff --git a/plotly/plotlykt-jupyter/api/plotlykt-jupyter.api b/plotly/plotlykt-jupyter/api/plotlykt-jupyter.api new file mode 100644 index 00000000..6326424f --- /dev/null +++ b/plotly/plotlykt-jupyter/api/plotlykt-jupyter.api @@ -0,0 +1,18 @@ +public final class space/kscience/plotly/PlotlyIntegration : org/jetbrains/kotlinx/jupyter/api/libraries/JupyterIntegration, space/kscience/plotly/PlotlyRenderer { + public fun <init> ()V + public fun onLoaded (Lorg/jetbrains/kotlinx/jupyter/api/libraries/JupyterIntegration$Builder;)V + public fun renderPlot (Lkotlinx/html/FlowContent;Lspace/kscience/plotly/Plot;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;)Lspace/kscience/plotly/Plot; +} + +public final class space/kscience/plotly/PlotlyIntegrationKt { + public static final fun getJupyter (Lspace/kscience/plotly/Plotly;)Lspace/kscience/plotly/PlotlyJupyterConfiguration; +} + +public final class space/kscience/plotly/PlotlyJupyterConfiguration { + public static final field INSTANCE Lspace/kscience/plotly/PlotlyJupyterConfiguration; + public final fun getLegacyMode ()Z + public final fun lab ()Lspace/kscience/plotly/PlotlyHtmlFragment; + public final fun notebook ()Lspace/kscience/plotly/PlotlyHtmlFragment; + public final fun setLegacyMode (Z)V +} + diff --git a/plotly/plotlykt-jupyter/build.gradle.kts b/plotly/plotlykt-jupyter/build.gradle.kts new file mode 100644 index 00000000..2258c89a --- /dev/null +++ b/plotly/plotlykt-jupyter/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + id("space.kscience.gradle.mpp") + kotlin("jupyter.api") + `maven-publish` +} + +val dataforgeVersion: String by rootProject.extra + +kscience{ + jvm() + jvmMain{ + api(projects.plotly.plotlyktCore) + } +} + +tasks.processJupyterApiResources{ + libraryProducers = listOf("space.kscience.plotly.PlotlyIntegration") +} \ No newline at end of file diff --git a/plotly/plotlykt-jupyter/src/jvmMain/kotlin/space/kscience/plotly/PlotlyIntegration.kt b/plotly/plotlykt-jupyter/src/jvmMain/kotlin/space/kscience/plotly/PlotlyIntegration.kt new file mode 100644 index 00000000..dc0d197b --- /dev/null +++ b/plotly/plotlykt-jupyter/src/jvmMain/kotlin/space/kscience/plotly/PlotlyIntegration.kt @@ -0,0 +1,137 @@ +package space.kscience.plotly + +import kotlinx.html.* +import kotlinx.html.stream.createHTML +import org.jetbrains.kotlinx.jupyter.api.HTML +import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration +import org.jetbrains.kotlinx.jupyter.api.libraries.resources + +public object PlotlyJupyterConfiguration { + public var legacyMode: Boolean = false + + /** + * Switch plotly renderer to the legacy notebook mode (Jupyter classic) + */ + public fun notebook(): PlotlyHtmlFragment { + legacyMode = true + return PlotlyHtmlFragment { + div { + style = "color: blue;" + +"Plotly notebook integration switched into the notebook mode." + } + } + } + + public fun lab(): PlotlyHtmlFragment { + legacyMode = false + return PlotlyHtmlFragment { + div { + style = "color: blue;" + +"Plotly notebook integration switched into the lab mode." + } + } + } +} + +/** + * Global plotly jupyter configuration + */ +public val Plotly.jupyter: PlotlyJupyterConfiguration + get() = PlotlyJupyterConfiguration + +public class PlotlyIntegration : JupyterIntegration(), PlotlyRenderer { + override fun FlowContent.renderPlot(plot: Plot, plotId: String, config: PlotlyConfig): Plot { + div { + id = plotId + script { + unsafe { + //language=JavaScript + +""" + if(typeof Plotly !== "undefined"){ + Plotly.react( + '$plotId', + ${plot.data.toJsonString()}, + ${plot.layout.toJsonString()}, + ${config.toJsonString()} + ); + } else { + console.error("Plotly not loaded") + } + """.trimIndent() + } + } + } + return plot + } + + private fun renderPlot(plot: Plot): String = createHTML().div { + plot(plot, config = PlotlyConfig { + responsive = true + }, renderer = this@PlotlyIntegration) + } + + private fun renderFragment(fragment: PlotlyFragment): String = createHTML().div { + with(fragment) { + render(this@PlotlyIntegration) + } + } + + private fun renderPage(page: PlotlyPage): String = page.copy(renderer = this@PlotlyIntegration).render() + + override fun Builder.onLoaded() { + + resources { + js("plotly-kt") { + url("https://cdn.plot.ly/plotly-2.29.1.min.js") + classPath("js/plotly-kt.js") + } + } + + repositories("https://repo.kotlin.link") + + import( + "space.kscience.plotly.*", + "space.kscience.plotly.models.*", + "space.kscience.dataforge.meta.*", + "kotlinx.html.*" + ) + + import("space.kscience.plotly.jupyter") + + render<PlotlyHtmlFragment> { + HTML(it.toString()) + } + + val renderer = this@PlotlyIntegration + + render<Plot> { plot -> + if (PlotlyJupyterConfiguration.legacyMode) { + HTML( + Plotly.page(renderer = renderer) { + plot(renderer = renderer, plot = plot) + }.render(), + true + ) + } else { + HTML(renderPlot(plot), false) + } + } + + render<PlotlyFragment> { fragment -> + if (PlotlyJupyterConfiguration.legacyMode) { + HTML( + Plotly.page(renderer = renderer) { renderer -> + fragment.render(this, renderer) + }.render(), true + ) + } else { + HTML(renderFragment(fragment), false) + } + } + + render<PlotlyPage> { + HTML(renderPage(it), true) + } + } + +} diff --git a/plotly/plotlykt-script/README.md b/plotly/plotlykt-script/README.md new file mode 100644 index 00000000..692a74a4 --- /dev/null +++ b/plotly/plotlykt-script/README.md @@ -0,0 +1,21 @@ +# Module plotlykt-script + + + +## Usage + +## Artifact: + +The Maven coordinates of this project are `space.kscience:plotlykt-script:0.7.1`. + +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:plotlykt-script:0.7.1") +} +``` diff --git a/plotly/plotlykt-script/api/plotlykt-script.api b/plotly/plotlykt-script/api/plotlykt-script.api new file mode 100644 index 00000000..9fc1251b --- /dev/null +++ b/plotly/plotlykt-script/api/plotlykt-script.api @@ -0,0 +1,21 @@ +public final class space/kscience/plotly/script/BuilderKt { + public static final fun page (Lspace/kscience/plotly/Plotly;Ljava/io/File;Ljava/lang/String;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lmu/KLogger;)Lspace/kscience/plotly/PlotlyPage; + public static final fun page (Lspace/kscience/plotly/Plotly;Ljava/lang/String;Ljava/lang/String;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lmu/KLogger;)Lspace/kscience/plotly/PlotlyPage; + public static final fun page (Lspace/kscience/plotly/Plotly;Lkotlin/script/experimental/api/SourceCode;Ljava/lang/String;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lmu/KLogger;)Lspace/kscience/plotly/PlotlyPage; + public static synthetic fun page$default (Lspace/kscience/plotly/Plotly;Ljava/io/File;Ljava/lang/String;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lmu/KLogger;ILjava/lang/Object;)Lspace/kscience/plotly/PlotlyPage; + public static synthetic fun page$default (Lspace/kscience/plotly/Plotly;Ljava/lang/String;Ljava/lang/String;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lmu/KLogger;ILjava/lang/Object;)Lspace/kscience/plotly/PlotlyPage; + public static synthetic fun page$default (Lspace/kscience/plotly/Plotly;Lkotlin/script/experimental/api/SourceCode;Ljava/lang/String;[Lspace/kscience/plotly/PlotlyHtmlFragment;Lmu/KLogger;ILjava/lang/Object;)Lspace/kscience/plotly/PlotlyPage; +} + +public final class space/kscience/plotly/script/CliKt { + public static final fun main ([Ljava/lang/String;)V +} + +public abstract class space/kscience/plotly/script/PlotlyScript { + public fun <init> ()V +} + +public final class space/kscience/plotly/script/PlotlyScriptCompilationConfiguration : kotlin/script/experimental/api/ScriptCompilationConfiguration { + public fun <init> ()V +} + diff --git a/plotly/plotlykt-script/build.gradle.kts b/plotly/plotlykt-script/build.gradle.kts new file mode 100644 index 00000000..9584e597 --- /dev/null +++ b/plotly/plotlykt-script/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + id("space.kscience.gradle.mpp") + application + `maven-publish` +} + +val ktorVersion: String by rootProject.extra +val dataforgeVersion: String by rootProject.extra + +kscience{ + jvm{ + withJava() + } + jvmMain{ + api(projects.plotly.plotlyktCore) + api(spclibs.kotlinx.html) + api(kotlin("scripting-jvm-host")) + api(kotlin("scripting-jvm")) + api("io.github.microutils:kotlin-logging:3.0.5") + implementation(spclibs.logback.classic) + implementation(spclibs.kotlinx.cli) + } +} + + +application{ + mainClass.set("space.kscience.plotly.script.CliKt") +} \ No newline at end of file diff --git a/plotly/plotlykt-script/src/jvmMain/kotlin/space/kscience/plotly/script/PlotlyScript.kt b/plotly/plotlykt-script/src/jvmMain/kotlin/space/kscience/plotly/script/PlotlyScript.kt new file mode 100644 index 00000000..8a6b051d --- /dev/null +++ b/plotly/plotlykt-script/src/jvmMain/kotlin/space/kscience/plotly/script/PlotlyScript.kt @@ -0,0 +1,35 @@ +package space.kscience.plotly.script + +import kotlinx.html.FlowContent +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.* +import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration +import kotlin.script.experimental.jvm.dependenciesFromCurrentContext +import kotlin.script.experimental.jvm.jvm + +@KotlinScript( + fileExtension = "plotly.kts", + compilationConfiguration = PlotlyScriptCompilationConfiguration::class +) +public abstract class PlotlyScript + + +public class PlotlyScriptCompilationConfiguration: ScriptCompilationConfiguration({ + baseClass(PlotlyScript::class) + implicitReceivers(FlowContent::class) + defaultImports( + "kotlin.math.*", + "space.kscience.plotly.*", + "space.kscience.plotly.models.*", + "space.kscience.dataforge.meta.*", + "kotlinx.html.*" + ) + jvm { + dependenciesFromCurrentContext(wholeClasspath = true) + compilerOptions.append("-jvm-target", Runtime.version().feature().toString()) + } + hostConfiguration(defaultJvmScriptingHostConfiguration) + ide { + acceptedLocations(ScriptAcceptedLocation.Everywhere) + } +}) \ No newline at end of file diff --git a/plotly/plotlykt-script/src/jvmMain/kotlin/space/kscience/plotly/script/builder.kt b/plotly/plotlykt-script/src/jvmMain/kotlin/space/kscience/plotly/script/builder.kt new file mode 100644 index 00000000..82981317 --- /dev/null +++ b/plotly/plotlykt-script/src/jvmMain/kotlin/space/kscience/plotly/script/builder.kt @@ -0,0 +1,76 @@ +package space.kscience.plotly.script + +import kotlinx.html.FlowContent +import mu.KLogger +import mu.KotlinLogging +import space.kscience.plotly.* +import java.io.File +import kotlin.script.experimental.api.* +import kotlin.script.experimental.host.toScriptSource +import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration +import kotlin.script.experimental.jvm.dependenciesFromCurrentContext +import kotlin.script.experimental.jvm.jvm +import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost + +@UnstablePlotlyAPI +public fun Plotly.page( + source: SourceCode, + title: String = "Plotly.kt", + headers: Array<PlotlyHtmlFragment> = arrayOf(cdnPlotlyHeader), + logger: KLogger = KotlinLogging.logger("scripting") +): PlotlyPage { + + val workspaceScriptConfiguration = ScriptCompilationConfiguration { + baseClass(PlotlyScript::class) + implicitReceivers(FlowContent::class) + defaultImports( + "kotlin.math.*", + "space.kscience.plotly.*", + "space.kscience.plotly.models.*", + "space.kscience.dataforge.meta.*", + "kotlinx.html.*" + ) + jvm { + dependenciesFromCurrentContext(wholeClasspath = true) + compilerOptions.append("-jvm-target", Runtime.version().feature().toString()) + } + hostConfiguration(defaultJvmScriptingHostConfiguration) + } + + return page(title = title, headers = headers) { + val flow = this + val evaluationConfiguration = ScriptEvaluationConfiguration { + implicitReceivers(flow) + } + BasicJvmScriptingHost().eval(source, workspaceScriptConfiguration, evaluationConfiguration).onFailure { + it.reports.forEach { scriptDiagnostic -> + when (scriptDiagnostic.severity) { + ScriptDiagnostic.Severity.FATAL, ScriptDiagnostic.Severity.ERROR -> { + logger.error(scriptDiagnostic.exception) { scriptDiagnostic.toString() } + error(scriptDiagnostic.toString()) + } + ScriptDiagnostic.Severity.WARNING -> logger.warn { scriptDiagnostic.toString() } + ScriptDiagnostic.Severity.INFO -> logger.info { scriptDiagnostic.toString() } + ScriptDiagnostic.Severity.DEBUG -> logger.debug { scriptDiagnostic.toString() } + } + } + } + } +} + +@UnstablePlotlyAPI +public fun Plotly.page( + file: File, + title: String = "Plotly.kt", + headers: Array<PlotlyHtmlFragment> = arrayOf(cdnPlotlyHeader), + logger: KLogger = KotlinLogging.logger("scripting") +): PlotlyPage = page(file.toScriptSource(), title, headers, logger) + + +@OptIn(UnstablePlotlyAPI::class) +public fun Plotly.page( + string: String, + title: String = "Plotly.kt", + headers: Array<PlotlyHtmlFragment> = arrayOf(cdnPlotlyHeader), + logger: KLogger = KotlinLogging.logger("scripting") +): PlotlyPage = page(string.toScriptSource(), title, headers, logger) \ No newline at end of file diff --git a/plotly/plotlykt-script/src/jvmMain/kotlin/space/kscience/plotly/script/cli.kt b/plotly/plotlykt-script/src/jvmMain/kotlin/space/kscience/plotly/script/cli.kt new file mode 100644 index 00000000..1c188f46 --- /dev/null +++ b/plotly/plotlykt-script/src/jvmMain/kotlin/space/kscience/plotly/script/cli.kt @@ -0,0 +1,27 @@ +package space.kscience.plotly.script + +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlinx.cli.optional +import space.kscience.plotly.Plotly +import space.kscience.plotly.UnstablePlotlyAPI +import space.kscience.plotly.makeFile +import java.io.File +import java.nio.file.Path + +@OptIn(UnstablePlotlyAPI::class) +public fun main(args: Array<String>) { + val parser = ArgParser("plotlykt-script") + val input by parser.argument(ArgType.String, description ="Input file path") + val output by parser.argument(ArgType.String, description = "Output file path").optional() + val title by parser.option(ArgType.String, fullName = "title", description = "Plot title") + parser.parse(args) + + require(input.endsWith("plotly.kts")) + + val inputFile: File = File(input) + val page = Plotly.page(inputFile, title = (title ?: "Plotly.kt")) + + val outputFile: Path? = output?.let{ Path.of(output)} + page.makeFile(outputFile) +} \ No newline at end of file diff --git a/plotly/plotlykt-script/src/jvmMain/resources/META-INF/kotlin/script/templates/space.kscience.plotly.script.PlotlyScript.classname b/plotly/plotlykt-script/src/jvmMain/resources/META-INF/kotlin/script/templates/space.kscience.plotly.script.PlotlyScript.classname new file mode 100644 index 00000000..e69de29b diff --git a/plotly/plotlykt-script/src/jvmTest/kotlin/space/kscience/plotly/script/BuilderTest.kt b/plotly/plotlykt-script/src/jvmTest/kotlin/space/kscience/plotly/script/BuilderTest.kt new file mode 100644 index 00000000..3271253d --- /dev/null +++ b/plotly/plotlykt-script/src/jvmTest/kotlin/space/kscience/plotly/script/BuilderTest.kt @@ -0,0 +1,13 @@ +package space.kscience.plotly.script + +import org.junit.jupiter.api.Test +import space.kscience.plotly.Plotly + +internal class BuilderTest { + @Test + fun testBuilderFromString() { + val string = javaClass.getResource("/customPage.plotly.kts").readText() + val page = Plotly.page(string) + println(page.render()) + } +} \ No newline at end of file diff --git a/plotly/plotlykt-script/src/jvmTest/resources/customPage.plotly.kts b/plotly/plotlykt-script/src/jvmTest/resources/customPage.plotly.kts new file mode 100644 index 00000000..2e91ec1f --- /dev/null +++ b/plotly/plotlykt-script/src/jvmTest/resources/customPage.plotly.kts @@ -0,0 +1,29 @@ +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" } + + +plot { + 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" + } + } +} diff --git a/plotly/plotlykt-server/README.md b/plotly/plotlykt-server/README.md new file mode 100644 index 00000000..59e5a1ac --- /dev/null +++ b/plotly/plotlykt-server/README.md @@ -0,0 +1,21 @@ +# Module plotlykt-server + + + +## Usage + +## Artifact: + +The Maven coordinates of this project are `space.kscience:plotlykt-server:0.7.1`. + +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:plotlykt-server:0.7.1") +} +``` diff --git a/plotly/plotlykt-server/api/plotlykt-server.api b/plotly/plotlykt-server/api/plotlykt-server.api new file mode 100644 index 00000000..8903650d --- /dev/null +++ b/plotly/plotlykt-server/api/plotlykt-server.api @@ -0,0 +1,100 @@ +public final class space/kscience/plotly/server/MetaChangeCollector { + public fun <init> ()V + public final fun collect (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun read (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class space/kscience/plotly/server/MetaChangeCollectorKt { + public static final fun collectUpdates (Lspace/kscience/plotly/Plot;Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;I)Lkotlinx/coroutines/flow/Flow; +} + +public final class space/kscience/plotly/server/PlotlyServer : kotlinx/coroutines/CoroutineScope, space/kscience/dataforge/meta/Configurable { + public static final field Companion Lspace/kscience/plotly/server/PlotlyServer$Companion; + public static final field DEFAULT_PAGE Ljava/lang/String; + public final fun getApplication ()Lio/ktor/server/application/Application; + public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext; + public final fun getDataSourceHost ()Ljava/lang/String; + public final fun getDataSourcePort ()Ljava/lang/Integer; + public final fun getEmbedData ()Z + public synthetic fun getMeta ()Lspace/kscience/dataforge/meta/MutableMeta; + public fun getMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public final fun getUpdateInterval ()I + public final fun getUpdateMode ()Lspace/kscience/plotly/server/PlotlyUpdateMode; + public final fun header (Lkotlin/jvm/functions/Function1;)V + public final fun page (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlin/jvm/functions/Function2;)V + public final fun page (Lspace/kscience/plotly/PlotlyFragment;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)V + public static synthetic fun page$default (Lspace/kscience/plotly/server/PlotlyServer;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V + public static synthetic fun page$default (Lspace/kscience/plotly/server/PlotlyServer;Lspace/kscience/plotly/PlotlyFragment;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;ILjava/lang/Object;)V + public final fun setDataSourceHost (Ljava/lang/String;)V + public final fun setDataSourcePort (Ljava/lang/Integer;)V + public final fun setEmbedData (Z)V + public final fun setUpdateInterval (I)V + public final fun setUpdateMode (Lspace/kscience/plotly/server/PlotlyUpdateMode;)V +} + +public final class space/kscience/plotly/server/PlotlyServer$Companion { + public final fun getUPDATE_INTERVAL_KEY ()Lspace/kscience/dataforge/names/Name; + public final fun getUPDATE_MODE_KEY ()Lspace/kscience/dataforge/names/Name; +} + +public final class space/kscience/plotly/server/PlotlyServerConfiguration : space/kscience/dataforge/meta/Scheme { + public static final field INSTANCE Lspace/kscience/plotly/server/PlotlyServerConfiguration; + public final fun getLegacyMode ()Z + public final fun getPort ()I + public final fun getUpdateInterval ()I + public final fun notebook ()Lspace/kscience/plotly/PlotlyHtmlFragment; + public final fun setLegacyMode (Z)V + public final fun setPort (I)V + public final fun setUpdateInterval (I)V +} + +public final class space/kscience/plotly/server/PlotlyServerIntegration : org/jetbrains/kotlinx/jupyter/api/libraries/JupyterIntegration { + public fun <init> ()V + public final fun isServerStarted ()Z + public fun onLoaded (Lorg/jetbrains/kotlinx/jupyter/api/libraries/JupyterIntegration$Builder;)V +} + +public final class space/kscience/plotly/server/PlotlyServerIntegrationKt { + public static final fun getJupyter (Lspace/kscience/plotly/Plotly;)Lspace/kscience/plotly/server/PlotlyServerConfiguration; +} + +public final class space/kscience/plotly/server/PlotlyServerKt { + public static final fun close (Lio/ktor/server/engine/ApplicationEngine;)V + public static final fun plot (Lspace/kscience/plotly/server/PlotlyServer;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;Lkotlin/jvm/functions/Function1;)V + public static synthetic fun plot$default (Lspace/kscience/plotly/server/PlotlyServer;Ljava/lang/String;Lspace/kscience/plotly/PlotlyConfig;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V + public static final fun plotlyModule (Lio/ktor/server/application/Application;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lspace/kscience/plotly/server/PlotlyServer; + public static synthetic fun plotlyModule$default (Lio/ktor/server/application/Application;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/plotly/server/PlotlyServer; + public static final fun pullUpdates (Lspace/kscience/plotly/server/PlotlyServer;I)Lspace/kscience/plotly/server/PlotlyServer; + public static synthetic fun pullUpdates$default (Lspace/kscience/plotly/server/PlotlyServer;IILjava/lang/Object;)Lspace/kscience/plotly/server/PlotlyServer; + public static final fun pushUpdates (Lspace/kscience/plotly/server/PlotlyServer;I)Lspace/kscience/plotly/server/PlotlyServer; + public static synthetic fun pushUpdates$default (Lspace/kscience/plotly/server/PlotlyServer;IILjava/lang/Object;)Lspace/kscience/plotly/server/PlotlyServer; + public static final fun serve (Lspace/kscience/plotly/Plotly;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;ILkotlin/jvm/functions/Function1;)Lio/ktor/server/engine/ApplicationEngine; + public static synthetic fun serve$default (Lspace/kscience/plotly/Plotly;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/ktor/server/engine/ApplicationEngine; + public static final fun show (Lio/ktor/server/engine/ApplicationEngine;)V +} + +public final class space/kscience/plotly/server/PlotlyUpdateMode : java/lang/Enum { + public static final field NONE Lspace/kscience/plotly/server/PlotlyUpdateMode; + public static final field PULL Lspace/kscience/plotly/server/PlotlyUpdateMode; + public static final field PUSH Lspace/kscience/plotly/server/PlotlyUpdateMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/plotly/server/PlotlyUpdateMode; + public static fun values ()[Lspace/kscience/plotly/server/PlotlyUpdateMode; +} + +public abstract class space/kscience/plotly/server/Update { + public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getId ()Ljava/lang/String; + public abstract fun toJson ()Lkotlinx/serialization/json/JsonObject; +} + +public final class space/kscience/plotly/server/Update$Layout : space/kscience/plotly/server/Update { + public fun <init> (Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V + public fun toJson ()Lkotlinx/serialization/json/JsonObject; +} + +public final class space/kscience/plotly/server/Update$Trace : space/kscience/plotly/server/Update { + public fun <init> (Ljava/lang/String;ILspace/kscience/dataforge/meta/Meta;)V + public fun toJson ()Lkotlinx/serialization/json/JsonObject; +} + diff --git a/plotly/plotlykt-server/build.gradle.kts b/plotly/plotlykt-server/build.gradle.kts new file mode 100644 index 00000000..719ea8d8 --- /dev/null +++ b/plotly/plotlykt-server/build.gradle.kts @@ -0,0 +1,27 @@ +import space.kscience.gradle.KScienceVersions + +plugins { + id("space.kscience.gradle.mpp") + kotlin("jupyter.api") + `maven-publish` +} + +val dataforgeVersion: String by rootProject.extra +val ktorVersion = KScienceVersions.ktorVersion + +kscience{ + jvm() + useCoroutines() + commonMain{ + api(projects.plotly.plotlyktCore) + api("io.ktor:ktor-server-cio:$ktorVersion") + api("io.ktor:ktor-server-html-builder:$ktorVersion") + api("io.ktor:ktor-server-websockets:$ktorVersion") + api("io.ktor:ktor-server-cors:$ktorVersion") + api("space.kscience:dataforge-context:$dataforgeVersion") + } +} + +tasks.processJupyterApiResources{ + libraryProducers = listOf("space.kscience.plotly.server.PlotlyServerIntegration") +} \ No newline at end of file diff --git a/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/MetaChangeCollector.kt b/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/MetaChangeCollector.kt new file mode 100644 index 00000000..e526df1a --- /dev/null +++ b/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/MetaChangeCollector.kt @@ -0,0 +1,74 @@ +package space.kscience.plotly.server + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.transform +import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.asName +import space.kscience.plotly.Plot + + +/** + * A change collector that combines all emitted configuration changes until read, than drops all collected changes + * and starts new batch. + */ +public class MetaChangeCollector { + private val mutex = Mutex() + private var state = MutableMeta() + + public suspend fun collect(name: Name, newItem: Meta?) { + mutex.withLock { + state[name] = newItem + } + } + + public suspend fun read(): Meta { + return if (!state.isEmpty()) { + mutex.withLock { + state.seal().also { + state = MutableMeta() + } + } + } else { + Meta.EMPTY + } + } +} + +private fun ObservableMeta.collectChanges(scope: CoroutineScope): MetaChangeCollector = MetaChangeCollector().apply { + onChange(this) { name -> + scope.launch { + collect(name, get(name)) + } + } +} + +private fun ObservableMeta.flowChanges(scope: CoroutineScope, updateInterval: Int): Flow<Meta> { + val collector = collectChanges(scope) + return flow { + while (true) { + delay(updateInterval.toLong()) + val meta = collector.read() + if (!meta.isEmpty()) { + emit(meta) + } + } + } +} + +public fun Plot.collectUpdates( + plotId: String, + scope: CoroutineScope, + updateInterval: Int, +): Flow<Update> = meta.flowChanges(scope, updateInterval).transform { change -> + change["layout"]?.let{ emit(Update.Layout(plotId, it))} + change.getIndexed("data".asName()).forEach { (index, metaItem) -> + emit(Update.Trace(plotId, index?.toInt() ?: 0, metaItem)) + } +} \ No newline at end of file diff --git a/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServer.kt b/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServer.kt new file mode 100644 index 00000000..d08a057c --- /dev/null +++ b/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServer.kt @@ -0,0 +1,337 @@ +package space.kscience.plotly.server + +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.engine.ApplicationEngine +import io.ktor.server.engine.embeddedServer +import io.ktor.server.html.respondHtml +import io.ktor.server.http.content.staticResources +import io.ktor.server.plugins.cors.routing.CORS +import io.ktor.server.plugins.origin +import io.ktor.server.response.respond +import io.ktor.server.response.respondText +import io.ktor.server.routing.* +import io.ktor.server.websocket.WebSockets +import io.ktor.server.websocket.webSocket +import io.ktor.websocket.Frame +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.GlobalScope +import kotlinx.html.* +import kotlinx.serialization.json.JsonObject +import space.kscience.dataforge.meta.* +import space.kscience.dataforge.names.Name +import space.kscience.plotly.* +import space.kscience.plotly.server.PlotlyServer.Companion.DEFAULT_PAGE +import java.awt.Desktop +import java.net.URI +import kotlin.collections.set +import kotlin.coroutines.CoroutineContext + +public enum class PlotlyUpdateMode { + NONE, + PUSH, + PULL +} + +internal class ServerPlotlyRenderer( + val baseUrl: Url, + val updateMode: PlotlyUpdateMode, + val updateInterval: Int, + val embedData: Boolean, + val plotCallback: (plotId: String, plot: Plot) -> Unit, +) : PlotlyRenderer { + override fun FlowContent.renderPlot(plot: Plot, plotId: String, config: PlotlyConfig): Plot { + plotCallback(plotId, plot) + div { + id = plotId + + val dataUrl = URLBuilder(baseUrl).apply { + encodedPath = baseUrl.encodedPath + "/data/$plotId" + }.build() + script { + if (embedData) { + unsafe { + //language=JavaScript + +""" + + plotlyConnect.makePlot( + '$plotId', + ${plot.data.toJsonString()}, + ${plot.layout.toJsonString()}, + $config + ); + + + """.trimIndent() + } + } else { + unsafe { + //language=JavaScript + +""" + + plotlyConnect.createPlotFrom('$plotId','$dataUrl', $config); + + """.trimIndent() + } + } + + // starting plot updates if required + when (updateMode) { + PlotlyUpdateMode.PUSH -> { + val wsUrl = URLBuilder(baseUrl).apply { + protocol = URLProtocol.WS + encodedPath = baseUrl.encodedPath + "/ws/$plotId" + }.build() + unsafe { + //language=JavaScript + +""" + + plotlyConnect.startPush('$plotId', '$wsUrl'); + + """.trimIndent() + } + } + + PlotlyUpdateMode.PULL -> { + unsafe { + //language=JavaScript + +""" + + plotlyConnect.startPull('$plotId', '$dataUrl', ${updateInterval}); + + """.trimIndent() + } + } + + PlotlyUpdateMode.NONE -> { + //do nothing + } + } + } + } + return plot + } + +} + +public class PlotlyServer internal constructor( + private val routing: Routing, private val rootRoute: String, +) : Configurable, CoroutineScope { + + override val coroutineContext: CoroutineContext get() = routing.application.coroutineContext + + override val meta: ObservableMutableMeta = ObservableMutableMeta() + public var updateMode: PlotlyUpdateMode by meta.enum(PlotlyUpdateMode.PUSH, key = UPDATE_MODE_KEY) + public var updateInterval: Int by meta.int(300, key = UPDATE_INTERVAL_KEY) + public var embedData: Boolean by meta.boolean(false) + + /** + * An override for data (pull/push) service host. By default uses request host + */ + public var dataSourceHost: String? by meta.string() + + /** + * An override for data (pull/push) service port. By default uses request port + */ + public var dataSourcePort: Int? by meta.int() + + internal val root by lazy { routing.createRouteFromPath(rootRoute) } + + /** + * a list of headers that should be applied to all pages + */ + private val globalHeaders: ArrayList<PlotlyHtmlFragment> = ArrayList<PlotlyHtmlFragment>() + + public fun header(block: TagConsumer<*>.() -> Unit) { + globalHeaders.add(PlotlyHtmlFragment(block)) + } + + internal fun Route.servePlotData(plots: Map<String, Plot>) { + //Update websocket + webSocket("ws/{id}") { + val plotId: String = call.parameters["id"] ?: error("Plot id not defined") + + application.log.debug("Opened server socket for $plotId") + + val plot = plots[plotId] ?: error("Plot with id='$plotId' not registered") + + try { + plot.collectUpdates(plotId, this, updateInterval).collect { update: Update -> + val json = update.toJson() + outgoing.send(Frame.Text(JsonObject(json).toString())) + } + } catch (ex: Exception) { + application.log.debug("Closed server socket for $plotId") + } + } + //Plots in their json representation + get("data/{id}") { + val id: String = call.parameters["id"] ?: error("Plot id not defined") + + val plot: Plot? = plots[id] + if (plot == null) { + call.respond(HttpStatusCode.NotFound, "Plot with id = $id not found") + } else { + call.respondText( + plot.toJsonString(), + contentType = ContentType.Application.Json, + status = HttpStatusCode.OK + ) + } + } + } + + public fun page( + plotlyFragment: PlotlyFragment, + route: String = DEFAULT_PAGE, + title: String = "Plotly server page '$route'", + headers: List<PlotlyHtmlFragment> = emptyList(), + ) { + root.apply { + val plots = HashMap<String, Plot>() + route(route) { + servePlotData(plots) + //filled pages + get { + val origin = call.request.origin + val url = URLBuilder().apply { + protocol = URLProtocol.createOrDefault(origin.scheme) + //workaround for https://github.com/ktorio/ktor/issues/1663 + host = dataSourceHost + ?: if (origin.serverHost.startsWith("0:")) "[${origin.serverHost}]" else origin.serverHost + port = dataSourcePort ?: origin.serverPort + encodedPath = origin.uri + }.build() + call.respondHtml { +// val normalizedRoute = if (rootRoute.endsWith("/")) { +// rootRoute +// } else { +// "$rootRoute/" +// } + + head { + meta { + charset = "utf-8" + (globalHeaders + headers).forEach { + it.visit(consumer) + } + plotlyKtHeader.visit(consumer) + } + title(title) + } + body { + val container = ServerPlotlyRenderer( + url, updateMode, updateInterval, embedData + ) { plotId, plot -> + plots[plotId] = plot + } + with(plotlyFragment) { + render(container) + } + } + } + } + } + } + } + + public fun page( + route: String = DEFAULT_PAGE, + title: String = "Plotly server page '$route'", + headers: List<PlotlyHtmlFragment> = emptyList(), + content: FlowContent.(renderer: PlotlyRenderer) -> Unit, + ) { + page(PlotlyFragment(content), route, title, headers) + } + + /** + * Exposes the Ktor application environment to internal logic + */ + public val application: Application get() = routing.application + + public companion object { + public const val DEFAULT_PAGE: String = "/" + public val UPDATE_MODE_KEY: Name = Name.parse("update.mode") + public val UPDATE_INTERVAL_KEY: Name = Name.parse("update.interval") + } +} + + +/** + * Attach plotly application to given server + */ +public fun Application.plotlyModule(route: String = DEFAULT_PAGE, block: PlotlyServer.() -> Unit = {}): PlotlyServer { + if (pluginOrNull(WebSockets) == null) { + install(WebSockets) + } + + routing { + route(route) { + staticResources("js", "js") + } + } + +// val root: Route = feature(Routing).createRouteFromPath(route) + return PlotlyServer(plugin(Routing), route).apply(block) +} + + +/** + * Configure server to start sending updates in push mode. Does not affect loaded pages + */ +public fun PlotlyServer.pushUpdates(interval: Int = 100): PlotlyServer = apply { + updateMode = PlotlyUpdateMode.PUSH + updateInterval = interval +} + +/** + * Configure client to request regular updates from server. Pull updates are more expensive than push updates since + * they contain the full plot data and server can't decide what to send. + */ +public fun PlotlyServer.pullUpdates(interval: Int = 500): PlotlyServer = apply { + updateMode = PlotlyUpdateMode.PULL + updateInterval = interval +} + +/** + * Start static server (updates via reload) + */ +@Suppress("ExtractKtorModule") +@OptIn(DelicateCoroutinesApi::class) +public fun Plotly.serve( + scope: CoroutineScope = GlobalScope, + host: String = "localhost", + port: Int = 7777, + block: PlotlyServer.() -> Unit, +): ApplicationEngine = scope.embeddedServer(io.ktor.server.cio.CIO, port, host) { +// install(CallLogging) + install(CORS) { + anyHost() + } + + plotlyModule(block = block) +}.start() + +/** + * A shortcut to make a single plot at the default page + */ +public fun PlotlyServer.plot( + plotId: String? = null, + config: PlotlyConfig = PlotlyConfig(), + plotBuilder: Plot.() -> Unit, +) { + page { plotly -> + div { + plot(plotId = plotId, config = config, renderer = plotly, builder = plotBuilder) + } + } +} + +public fun ApplicationEngine.show() { + val connector = environment.connectors.first() + val uri = URI("http", null, connector.host, connector.port, null, null, null) + Desktop.getDesktop().browse(uri) +} + +public fun ApplicationEngine.close(): Unit = stop(1000, 5000) \ No newline at end of file diff --git a/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServerIntegration.kt b/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServerIntegration.kt new file mode 100644 index 00000000..2ea82a3a --- /dev/null +++ b/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServerIntegration.kt @@ -0,0 +1,183 @@ +package space.kscience.plotly.server + +import io.ktor.http.URLBuilder +import io.ktor.server.engine.ApplicationEngine +import kotlinx.html.div +import kotlinx.html.script +import kotlinx.html.stream.createHTML +import kotlinx.html.style +import org.jetbrains.kotlinx.jupyter.api.HTML +import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration +import org.jetbrains.kotlinx.jupyter.api.libraries.resources +import org.slf4j.LoggerFactory +import space.kscience.dataforge.meta.Scheme +import space.kscience.dataforge.meta.boolean +import space.kscience.dataforge.meta.int +import space.kscience.plotly.* + +public object PlotlyServerConfiguration : Scheme() { + public var port: Int by int(System.getProperty("space.kscience.plotly.port")?.toInt() ?: 8882) + public var updateInterval: Int by int(100) + + public var legacyMode: Boolean by boolean(false) + + /** + * Switch plotly renderer to the legacy notebook mode (Jupyter classic) + */ + public fun notebook(): PlotlyHtmlFragment { + legacyMode = true + return PlotlyHtmlFragment { + div { + style = "color: blue;" + +"Plotly notebook integration switch into the legacy mode." + } + } + } +} + +internal val plotlyKtHeader = PlotlyHtmlFragment { + script { + src = "js/plotly-kt.js" + } +} + +/** + * Global plotly jupyter configuration + */ +public val Plotly.jupyter: PlotlyServerConfiguration + get() = PlotlyServerConfiguration + +public class PlotlyServerIntegration : JupyterIntegration() { + private val logger = LoggerFactory.getLogger(javaClass) + + private var server: ApplicationEngine? = null + + private val plots = HashMap<String, Plot>() + + private var renderer: PlotlyRenderer = StaticPlotlyRenderer + + public val isServerStarted: Boolean get() = server != null + + + private fun start(): PlotlyHtmlFragment = if (server != null) { + PlotlyHtmlFragment { + div { + style = "color: blue;" + +"The server is already running on ${Plotly.jupyter.port}. It must be shut down first to be restarted." + } + } + } else { + fun doStart(): PlotlyHtmlFragment { + server?.stop(1000, 1000) + server = Plotly.serve(host = "0.0.0.0", port = Plotly.jupyter.port) { + root.servePlotData(plots) + } + val serverUrl = URLBuilder(port = Plotly.jupyter.port).build() + renderer = ServerPlotlyRenderer( + serverUrl, PlotlyUpdateMode.PUSH, + Plotly.jupyter.updateInterval, + true + ) { plotId, plot -> + plots[plotId] = plot + } + return PlotlyHtmlFragment { + div { + style = "color: blue;" + +"Started plotly server on ${Plotly.jupyter.port}" + } + } + } + Plotly.jupyter.meta.onChange(this) { name -> + if (name.toString() != PlotlyServerConfiguration::legacyMode.name) { + logger.info("Plotly server config parameter $name changed. Restarting server.") + doStart() + } + } + logger.info("Starting Plotly-kt data server with ${Plotly.jupyter}") + doStart() + } + + private fun stop() { + logger.info("Stopping Plotly-kt update server") + server?.stop(1000, 1000) + server = null + } + + private fun renderPlot(plot: Plot): String = createHTML().div { + plot(plot, config = PlotlyConfig { + responsive = true + }, renderer = renderer) + } + + private fun renderFragment(fragment: PlotlyFragment): String = createHTML().div { + with(fragment) { + render(renderer) + } + } + + override fun Builder.onLoaded() { + + resources { + js("plotly-kt") { + classPath("js/plotly-kt.js") + } + } + + repositories("https://repo.kotlin.link") + + import( + "space.kscience.plotly.*", + "space.kscience.plotly.models.*", + "space.kscience.dataforge.meta.*", + "kotlinx.html.*", + "kotlinx.coroutines.*" + ) + + import("space.kscience.plotly.server.jupyter") + + render<PlotlyHtmlFragment> { + HTML(it.toString()) + } + + render<Plot> { plot -> + if (Plotly.jupyter.legacyMode) { + HTML( + Plotly.page(plotlyKtHeader, renderer = renderer) { + plot(renderer = renderer, plot = plot) + }.render(), true + ) + } else { + HTML(renderPlot(plot)) + } + } + + render<PlotlyFragment> { fragment -> + if (Plotly.jupyter.legacyMode) { + HTML( + Plotly.page(plotlyKtHeader, renderer = renderer) { renderer -> + fragment.render(this, renderer) + }.render(), true + ) + } else { + HTML(renderFragment(fragment)) + } + } + + render<PlotlyPage> { page -> + HTML(page.copy(headers = page.headers + plotlyKtHeader, renderer = renderer).render(), true) + } + + onLoaded { + logger.info("Starting Plotly-kt data server with ${Plotly.jupyter}") + val serverStart = start() + display(HTML(serverStart.toString()), null) + } + + onShutdown { + logger.info("Stopping Plotly-kt data server") + Plotly.jupyter.meta.removeListener(this) + display(HTML(stop().toString()), null) + } + } + +} diff --git a/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/Update.kt b/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/Update.kt new file mode 100644 index 00000000..a941b988 --- /dev/null +++ b/plotly/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/Update.kt @@ -0,0 +1,40 @@ +package space.kscience.plotly.server + +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.toJson +import space.kscience.plotly.Plotly + + +/** + * An update message for both data and layout + */ +public sealed class Update(public val id: String) { + public abstract fun toJson(): JsonObject + + public class Trace(id: String, private val trace: Int, private val content: Meta) : Update(id) { + override fun toJson(): JsonObject = buildJsonObject { + put("plotId", id) + put("contentType", "trace") + put("trace", trace) + //patch json to adhere to plotly array in array specification + val contentJson: JsonObject = content.toJson() as? JsonObject + ?: buildJsonObject { put("@value", content.toJson()) } + val patchedJson = contentJson + Plotly.coordinateNames.associateWith { contentJson[it] } + .filter { it.value != null } + .mapValues { JsonArray(listOf(it.value!!)) } + put("content", JsonObject(patchedJson)) + } + } + + public class Layout(id: String, private val content: Meta) : Update(id) { + override fun toJson(): JsonObject = buildJsonObject { + put("plotId", id) + put("contentType", "layout") + put("content", content.toJson()) + } + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 069ccb19..4994aa83 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -43,7 +43,6 @@ include( ":visionforge-compose-html", ":visionforge-compose-multiplatform", ":visionforge-solid", -// ":visionforge-fx", ":visionforge-threejs", ":visionforge-threejs:visionforge-threejs-server", ":visionforge-gdml", @@ -57,9 +56,19 @@ include( ":demo:muon-monitor", ":demo:sat-demo", ":demo:playground", -// ":demo:plotly-fx", ":demo:js-playground", ":demo:compose-desktop-demo", ":visionforge-jupyter", - ":visionforge-jupyter:visionforge-jupyter-common" + ":visionforge-jupyter:visionforge-jupyter-common", + ":plotly", + ":plotly:plotlykt-core", + ":plotly:plotlykt-geo", + ":plotly:plotlykt-jupyter", + ":plotly:plotlykt-server", + ":plotly:plotlykt-script", + ":plotly:examples", + ":plotly:examples:fx-demo", + ":plotly:examples:compose-demo", + ":plotly:examples:js-demo", + ":plotly:examples:native-demo" ) diff --git a/visionforge-compose-html/build.gradle.kts b/visionforge-compose-html/build.gradle.kts index 50d9f1e9..b05e1387 100644 --- a/visionforge-compose-html/build.gradle.kts +++ b/visionforge-compose-html/build.gradle.kts @@ -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 { diff --git a/visionforge-compose-html/src/jsMain/kotlin/bootstrap/Table.kt b/visionforge-compose-html/src/jsMain/kotlin/bootstrap/Table.kt index 1b4eb790..4647c247 100644 --- a/visionforge-compose-html/src/jsMain/kotlin/bootstrap/Table.kt +++ b/visionforge-compose-html/src/jsMain/kotlin/bootstrap/Table.kt @@ -9,18 +9,8 @@ import org.w3c.dom.HTMLDivElement import org.w3c.dom.HTMLTableCaptionElement import org.w3c.dom.HTMLTableCellElement import org.w3c.dom.HTMLTableElement -import kotlin.collections.List -import kotlin.collections.all -import kotlin.collections.chunked import kotlin.collections.component1 import kotlin.collections.component2 -import kotlin.collections.forEach -import kotlin.collections.forEachIndexed -import kotlin.collections.lastIndex -import kotlin.collections.map -import kotlin.collections.mapIndexed -import kotlin.collections.mutableListOf -import kotlin.collections.mutableMapOf import kotlin.collections.set import kotlin.math.max import kotlin.math.min @@ -110,9 +100,9 @@ public object Table { } public class FixedHeaderProperty(public val style: StyleScope.() -> Unit) { - public constructor(topSize: CSSLengthOrPercentageValue, zIndex: ZIndex) : this({ + public constructor(topSize: CSSLengthOrPercentageValue, zIndex: String) : this({ top(topSize) - property("z-index", zIndex.unsafeCast<String>()) + property("z-index", zIndex) }) } diff --git a/visionforge-compose-html/src/jsMain/kotlin/bootstrap/ZIndex.kt b/visionforge-compose-html/src/jsMain/kotlin/bootstrap/ZIndex.kt deleted file mode 100644 index 2e9e90da..00000000 --- a/visionforge-compose-html/src/jsMain/kotlin/bootstrap/ZIndex.kt +++ /dev/null @@ -1,18 +0,0 @@ -@file:Suppress( - "NAME_CONTAINS_ILLEGAL_CHARS", - "NESTED_CLASS_IN_EXTERNAL_INTERFACE", - "NOTHING_TO_INLINE", -) - -package bootstrap - -// language=JavaScript -@JsName("""(/*union*/{auto: 'auto'}/*union*/)""") -public sealed external interface ZIndex { - public companion object { - public val auto: ZIndex - } -} - -public inline fun ZIndex(value: Int): ZIndex = - value.unsafeCast<ZIndex>() diff --git a/visionforge-compose-multiplatform/build.gradle.kts b/visionforge-compose-multiplatform/build.gradle.kts index b3175b38..94ccab79 100644 --- a/visionforge-compose-multiplatform/build.gradle.kts +++ b/visionforge-compose-multiplatform/build.gradle.kts @@ -2,7 +2,8 @@ import space.kscience.gradle.Maturity plugins { id("space.kscience.gradle.mpp") - alias(spclibs.plugins.compose) + alias(spclibs.plugins.compose.compiler) + alias(spclibs.plugins.compose.jb) } kscience { diff --git a/visionforge-plotly/build.gradle.kts b/visionforge-plotly/build.gradle.kts index 81e5f60a..57aa1d54 100644 --- a/visionforge-plotly/build.gradle.kts +++ b/visionforge-plotly/build.gradle.kts @@ -2,8 +2,6 @@ plugins { id("space.kscience.gradle.mpp") } -val plotlyVersion = "0.7.0" - kscience { jvm() js { @@ -11,7 +9,7 @@ kscience { } dependencies { api(projects.visionforgeCore) - api("space.kscience:plotlykt-core:${plotlyVersion}") + api(projects.plotly.plotlyktCore) } useSerialization() } \ No newline at end of file diff --git a/visionforge-tables/build.gradle.kts b/visionforge-tables/build.gradle.kts index ccc0341a..9d3e1907 100644 --- a/visionforge-tables/build.gradle.kts +++ b/visionforge-tables/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("space.kscience.gradle.mpp") } -val tablesVersion = "0.4.0" +val tablesVersion = "0.4.1" kscience { jvm() diff --git a/visionforge-threejs/build.gradle.kts b/visionforge-threejs/build.gradle.kts index b066887c..60a00252 100644 --- a/visionforge-threejs/build.gradle.kts +++ b/visionforge-threejs/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("space.kscience.gradle.mpp") - alias(spclibs.plugins.compose) + alias(spclibs.plugins.compose.compiler) + alias(spclibs.plugins.compose.jb) } kotlin { diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt index b772c1bf..3bf23745 100644 --- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt +++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt @@ -1,11 +1,11 @@ package space.kscience.visionforge.solid.three import space.kscience.visionforge.solid.Convex -import three.external.geometries.ConvexBufferGeometry +import three.external.geometries.ConvexGeometry public object ThreeConvexFactory : ThreeMeshFactory<Convex>(Convex::class) { - override suspend fun buildGeometry(obj: Convex): ConvexBufferGeometry { + override suspend fun buildGeometry(obj: Convex): ConvexGeometry { val vectors = obj.points.map { it.toVector() }.toTypedArray() - return ConvexBufferGeometry(vectors) + return ConvexGeometry(vectors) } } \ No newline at end of file diff --git a/visionforge-threejs/src/jsMain/kotlin/three/external/geometries/ConvexGeometry.kt b/visionforge-threejs/src/jsMain/kotlin/three/external/geometries/ConvexGeometry.kt index 6c981460..0d8a7385 100644 --- a/visionforge-threejs/src/jsMain/kotlin/three/external/geometries/ConvexGeometry.kt +++ b/visionforge-threejs/src/jsMain/kotlin/three/external/geometries/ConvexGeometry.kt @@ -8,4 +8,4 @@ import three.math.Vector3 external class ConvexGeometry(points: Array<Vector3>) : BufferGeometry -external class ConvexBufferGeometry(points: Array<Vector3>) : BufferGeometry \ No newline at end of file +//external class ConvexBufferGeometry(points: Array<Vector3>) : BufferGeometry \ No newline at end of file diff --git a/visionforge-threejs/visionforge-threejs-server/build.gradle.kts b/visionforge-threejs/visionforge-threejs-server/build.gradle.kts index 3dbfacf4..80d1a11d 100644 --- a/visionforge-threejs/visionforge-threejs-server/build.gradle.kts +++ b/visionforge-threejs/visionforge-threejs-server/build.gradle.kts @@ -1,7 +1,8 @@ plugins { id("space.kscience.gradle.mpp") - alias(spclibs.plugins.compose) + alias(spclibs.plugins.compose.compiler) + alias(spclibs.plugins.compose.jb) } val ktorVersion: String by rootProject.extra