lightningchart.js 3D Box Series Spectrogram, how to CustomTick Using? - lightningchart

3D Box Series Spectrogram
const chart3D = lightningChart().Chart3D({
disableAnimations: true,
theme: Themes.lightNew,
})
.setTitle( '3D Box Series Spectrogram' )
.setBoundingBox( { x: 1, y: 1, z: 2 } )
chart3D.setCameraLocation( initialCameraLocation )
chart3D.getDefaultAxisY()
.setScrollStrategy( AxisScrollStrategies.expansion )
.setInterval( 0, 100 )
.setTitle( 'Power spectrum P(f)' )
const axisX= chart3D.getDefaultAxisX()
axisX.setTitle( 'Frequency (Hz)' )
axisX.setStrokeStyle(emptyLine)
axisX.setInterval(0, 256, false, true)
var tick = axisX.setTickStrategy( AxisTickStrategies.Numeric)
chart3D.getDefaultAxisZ()
.setTitle( 'Time' )
.setInterval( 0, -dataHistoryLength )
.setTickStrategy( AxisTickStrategies.Empty)
.setScrollStrategy( AxisScrollStrategies.progressive )
LightningChart.js Example 3D Box Series Spectrogram
xAxis AND yAxis Tick to 0,90,180,270,360 Change Way ??
chart3D getDefaultAxisX() addCustomTick is Not Working
Help Me

If I understood correctly, you want to have X axis ticks on following values: 0, 90, 180, 270 and 360, and nowhere else.
This is currently not possible. In 3D charts, only default tick placement is available. Manual tick placement (custom ticks) is currently only available in 2D charts.
While this is a feature we would eventually be adding, it doesn't have any priority at the moment as this is the first time we hear of a user needing it. If you need it for commercial purposes then please contact us https://www.arction.com/contact/
EDIT: Dedicated feature for 3D Custom Ticks has been accepted and will be released in a minor version release 2023.

Related

Bokeh circle height is incorrect [duplicate]

I am plotting some geometry using bokeh and came across this. I am plotting a rectangle with equal sides (i.e. a square), and in that square, plotting a circle with diameter = width of the square. The circle should tangent to the square at edges, but it is not.
here is the code:
from bokeh.plotting import output_notebook, figure, show
output_notebook()
p = figure(width=500, height=500)
p.rect(0, 0, 300, 300, line_color='black')
p.circle(x=0, y=0, radius=150, line_color='black',
fill_color='grey', radius_units='data')
p.axis.minor_tick_out = 0
show(p)
Which results in this:
Is there anything I am doing wrong or could change to make the circle fit exactly in the square?
Thanks in advance,
Randall
Here's another case - just drawing a circle:
p = figure(width=500, height=500, x_range=(-150, 150), y_range=(-150, 150))
p.circle(x=0, y=0, radius=150, line_color='black',
fill_color='grey', radius_units='data')
show(p)
radius of the circle is 150 in the x direction, but not the y-direction.
I would like to report that as of Bokeh 0.12.7, this issue can now be fixed in a simpler manner.
As described in other posts, the main issue is not that the circle is not a circle, but that the square is not a square. This is due to the fact that actual area on which Bokeh draws the figure (the canvas) is usually not a square by default or even when the width and height are set to the same value. Bokeh by default will attempt to draw a figure by using up all the space on the canvas. This creates a mismatch between the data distance and the pixel distance of the plot.
As of 0.12.7, figures can now accept a match_aspect property which when set to True will will match the aspect of the data space to the pixel space of the plot.
In your example, simply adding the match_aspect = True in your figure
p = figure(width=500, height=500, match_aspect=True,
title="Circle touches all 4 sides of square")
p.rect(0, 0, 300, 300, line_color='black')
p.circle(x=0, y=0, radius=150, line_color='black',
fill_color='grey', radius_units='data')
will now produce
UPDATE: Please note new answer by #DuCorey below. As of Bokeh 0.12.7, aspect control is now available, for situations like this.
The issue is actually that the square is not square, and that is because the pixel aspect ratio and the "data" aspect ratio do not match. i.e., the distance per pixel is different in the x direction than it is in the y direction.
There are a few options:
You can use various properties to control the dimensions of the central plot area (e.g. plot border width and axis tick label orientation) You can also control you data ranges explicitly. In other words, you can make the aspect ratios match, and then the circle and rect will match
You can use absolute pixel units (e.g. size for a circle, and use a large square marker instead of rect) instead of "data" units.
Alternatively, if you want a circle that "deforms" when the aspects do not match, then your best bet is to use an ellipse with an identical width and height, which will work because in this case bokeh has two dimensions to use to measure (instead of the single radius) and can match each to the scale along each dimension independently.
(This is actually the fundamental difference that explains the behaviour: rect has two dimensions to measure independently. circle does not, it only has one, and has to arbitrarily use the x or y dimension to measure distance per pixel)
ok, based on the suggestions, I tried a few things.
Changed the orientation of the y-axis tick labels - still
had issue.
Changed various stand-offs, even moving in the tick
labels inside the plot (with a negative offset). Did not work either.
Changed the x_range and r_range in figure() to be equal tuples. Did not work either
Changes the plot_height (decreased it), and I could eventually, through rial and error, get the circle to fit in the square with a plot_height that was < plot width.
Lots of great practice controlling attributes of the plot. Time will invested.
However, the last change I tried worked the best. It was one of the first suggestions - change the plot border.
Weirdly, setting p.min_border=40, which on 0.12.6 is the default value, and voila, it appears the chart aspect ratio for a chart where plot_width=plot_height is truly 1 on the screen as well.
p = figure(plot_width=500, plot_height=500)
p.rect(0, 0, 300, 300, line_color=None)
p.circle(x=0, y=0, radius=150, line_color=None,
fill_color='lightgrey', radius_units='data')
p.min_border=40
show(p)
Before and after images showing the effect of adding p.min_border=40. Any value over ~33 appeared to be enough force the plot area to have the same screen x and y dimension - so the square was really a square (and the circle fit inside).
The reason for this is that you're creating a circular marker (or circle glyphs) and placing it at position (0, 0), while it seems like you want to create a circle centered at 0.
I think the rect here "happens" to work because it can scale correctly in both dimensions and remain a "rectangle".
Keyword Args:
radius (UnitsSpecPropertyDescriptor) : The radius values for circle markers (in "data space" units, by default). (default None)
radius_dimension (BasicPropertyDescriptor) : What dimension to measure circle radii along. (default 'x')
radius_units (Enum('screen', 'data')) : (default 'data')
I guess my point is here you've taken a shortcut by trying to use a "glyph" as your plot and specifying the units to be the data units.
If you want to create an actual circle you could do the following:
th = np.linspace(0, 2*np.pi)
r = 150
p = figure(width=500, height=500)
p.rect(0, 0, 300, 300, line_color='black')
p.line(r * np.cos(th), r * np.sin(th), line_color='black')
# p.circle(x=0, y=0, radius=150, line_color='black',
# fill_color='grey', radius_units='data')
p.axis.minor_tick_out = 0
show(p)
Notice the above is harder to fill (I didn't bother) because I'm guessing you need to define some closed polygon function while I only defined a line that happens to be a closed polygon, in this case a circle.
Not sure, but the bleu rectangle is not your rectangle.
Replace:
p.rect(0, 0, 300, 300, line_color='black')
By:
p.rect(-150, -150, 150, 150, line_color='black')

How to plot shapes in Julia

I would like to plot for example a square (or maybe more generally speaking a n-gon).
I know that I can plot "functions" that form a shape, like a circle:
n = 100
ϕ = range(0,stop=2*π,length=n)
x = cos.(ϕ)';
y = sin.(ϕ)';
plot(x,y)
But that turns out to be very difficult when it comes to a n-gon,
I guess one could "stich" lines that can form a n-gon, but that seems very unpractical when you want to plot a 32-gon.
I talked a lot abou n-gons but I am more interested if Julia has some already build in way to plot different types of shapes.
You can use Luxor library, which provides ngon function (example from documentation).
using Luxor, Colors
Drawing(1200, 1400)
origin()
cols = diverging_palette(60, 120, 20) # hue 60 to hue 120
background(cols[1])
setopacity(0.7)
setline(2)
# circumradius of 500
ngon(0, 0, 500, 8, 0, :clip)
The documentation of the function itself can be found here.

How to select a region of an image in bokeh

In a web app, I would like to let the user select a region of interest in a plotted image using the nice box/lasso selection tools of bokeh. I would the like to receive the selected pixels for further operations in python.
For scatter plots, this is easy to do in analogy with the gallery,
import bokeh.plotting
import numpy as np
# data
X = np.linspace(0, 10, 20)
def f(x): return np.random.random(len(x))
# plot and add to document
fig = bokeh.plotting.figure(x_range=(0, 10), y_range=(0, 10),
tools="pan,wheel_zoom,box_select,lasso_select,reset")
plot = fig.scatter(X, f(X))
#plot = fig.image([np.random.random((10,10))*255], dw=[10], dh=[10])
bokeh.plotting.curdoc().add_root(fig)
# callback
def callback(attr, old, new):
# easily access selected points:
print sorted(new['1d']['indices'])
print sorted(plot.data_source.selected['1d']['indices'])
plot.data_source.data = {'x':X, 'y':f(X)}
plot.data_source.on_change('selected', callback)
however if I replace the scatter plot with
plot = fig.image([np.random.random((10,10))*255], dw=[10], dh=[10])
then using the selection tools on the image does not change anything in plot.data_source.selected.
I'm sure this is the intended behavior (and it makes sense too), but what if I want to select pixels of an image? I could of course put a grid of invisible scatter points on top of the image, but is there some more elegant way to accomplish this?
It sounds like the tool you're looking for is actually the BoxEditTool. Note that the BoxEditTool requires a list of glyphs (normally these will be Rect instances) that will render the ROIs, and that listening to changes should be set using:
rect_glyph_source.on_change('data', callback)
This will trigger the callback function any time you make any changes to your ROIs.
The relevant ColumnDataSource instance (rect_glyph_source in this example) will be updated so that the 'x' and 'y' keys list the center of each ROI in the image's coordinates space, and of course 'width' and 'height' describe its size. As far as I know there isn't currently a built-in method for extracting the data itself, so you will have to do something like:
rois = rect_glyph_source.data
roi_index = 0 # x, y, width and height are lists, and each ROI has its own index
x_center = rois['x'][roi_index]
width = rois['width'][roi_index]
y_center = rois['y'][roi_index]
height = rois['height'][roi_index]
x_start = int(x_center - 0.5 * width)
x_end = int(x_center + 0.5 * width)
y_start = int(y_center - 0.5 * height)
y_end = int(y_center + 0.5 * height)
roi_data = image_plot.source.data['image'][0][y_start:y_end, x_start:x_end]
IMPORTANT: In the current version of Bokeh (0.13.0) there is a problem with the synchronization of the BoxEditTool at the server and it isn't functional. This should be fixed in the next official Bokeh release. For more information and a temporary solution see this answer or this discussion.

Plot severals markers on a leaflet map

Hi i'm trying to learn how to use a leaflet map on shiny, I used that example :
http://glimmer.rstudio.com/jcheng/leaflet-demo/
Here is the code repository :
https://github.com/jcheng5/leaflet-shiny/blob/master/inst/example/
I'm would like to replace circles by markers by replacing the addCircle function by addMarker.
The actual function is :
(line 98 of Server.R)
map$addCircle(
cities$Lat,
cities$Long,
sqrt(cities[[popCol()]]) * radiusFactor / max(5, input$map_zoom)^2,
row.names(cities),
list(
weight=1.2,
fill=TRUE,
color='#4A9'
)
)
And I just replaced it by :
map$addMarker(
cities$Lat,
cities$Long,
row.names(cities)
)
But it only plot the marker on the first city of the data frame. And after if you move and zoom randomly on the map some other markers can appear...
Why addCircle draws a circle for each cities and addMarker behaves "randomly" ?
How can I draw severals marker at once on the plot ?
The loop bellow works but ideally I don't want to loop manually if it's possible.
for(i in 1:nrow(cities)){
map$addMarker(
cities$Lat[i],
cities$Long[i],
i
)
}
Thank you
I had the same problem, it is because you remove the radius. By looking at the code for the function createLeafletMap, we can see that addCircle needs these arguments:
addCircle(lat, lng, radius, layerId = NULL, options=list(), eachOptions=list())
it really need radius. to solve your problem just write:
map$addMarker(
cities$Lat,
cities$Long,
100,
row.names(cities)
)

How to draw a colorbar in rgl?

I have plotted a mesh in rgl to visualize data on it. I.e., the mesh has colors that originate from applying a colormap to its data (one scalar value at each vertex). Here is a minimal example that consists of a mesh with a single face:
library(rgl);
library(squash);
# create a mesh
vertices <- c(
-1.0, -1.0, 0, 1.0,
1.0, -1.0, 0, 1.0,
1.0, 1.0, 0, 1.0,
-1.0, 1.0, 0, 1.0
)
indices <- c( 1, 2, 3, 4 )
# add a data value for each vertex
morph_data = rnorm(length(indices), mean = 3, sd = 1)
# create colors from values by applying a colormap
col = squash::cmap(morph_data, map = squash::makecmap(morph_data, colFn = squash::jet));
# plot
open3d()
shade3d( qmesh3d(vertices, indices), col=col )
How can I add a colorbar to this plot in rgl?
An example for what exactly I mean with colorbar is shown in the right part of this example picture from octave.sourceforge.io.
You can use bgplot3d() to draw any sort of 2D plot in the background of an rgl plot. There are lots of different implementations of colorbars around; see Colorbar from custom colorRampPalette for a discussion. The last post in that thread was in 2014, so there may be newer solutions.
For example, using the fields::image.plot function, you can put this after your plot:
bgplot3d(fields::image.plot(legend.only = TRUE, zlim = range(morph_data), col = col) )
A documented disadvantage of this approach is that the window doesn't resize nicely; you should set your window size first, then add the colorbar. You'll also want to work on your definition of col to get more than 4 colors to show up if you do use image.plot.

Resources