I am trying stuff out with plotter-rs and I wanted to create an histogram with float values ranging from 0.0f64 to 1.0f64 and have like 50 segments.
Following is what I have been trying. .build_cartesion_2d() is the part that creates bars with a define range on the x and y axis.
use plotters::prelude::*;
use tch::{kind,Tensor};
let path = path.unwrap_or("plots/0.png");
let root = BitMapBackend::new(path, (1280, 720)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.set_label_area_size(LabelAreaPosition::Left, 40)
.set_label_area_size(LabelAreaPosition::Bottom, 40)
.caption("Histogram", ("sans-serif", 40))
.build_cartesian_2d((0i64..10).into_segmented(), 0i64..100)
.unwrap();
chart.configure_mesh().draw().unwrap();
let t = Tensor::rand(&[100], kind::FLOAT_CPU);
t.print();
let data: ndarray::ArrayD<f64> = (&t).try_into().unwrap();
root.draw_series(
Histogram::vertical(&chart)
.style(BLUE.filled())
.margin(10)
.data(data.map(|x| (((x*100.).round()/100.) as i64, 1))),
).unwrap();
Cargo.toml :
[package]
name = "test-rs"
version = "0.1.0"
edition = "2021"
[dependencies]
ndarray = "0.15.6"
plotters = "0.3.4"
tch = "0.10.1"```
Related
I'm doing my dissertetion and I need to make a streamplot with the velocities matrix.
I have resolved Navier-stokes equations and I have one matrix of u-velocity 19x67 and other matrix of v-velocity 19x67.
To obtain a continuos function I have done a bilinear interpolation but I have problem with the plotting.
I don't know if I explain myself very well but y let you the code.
#BILINEAR INTERPOLATION#
X=2
Y=0.67
x_pos=findlast(x->x<X, x)
y_pos=findlast(x->x<Y, y)
x1=((x_pos-1))*Dx
x2=(x_pos)*Dx
y1=((y_pos-1)-0.5)*Dy
y2=(y_pos-0.5)*Dy
u1=u[y_pos-1,x_pos-1]
u2=u[y_pos-1,x_pos]
u3=u[y_pos,x_pos-1]
u4=u[y_pos,x_pos]
u_int(Y,X)=(1/(Dx*Dy))*((x2.-X).*(y2.-Y).*u1+(X.-x1).*(y2.-Y).*u2+(x2.-X).*(Y.-y1).*u3+(X.-x1).*(Y.-y1).*u4)
xx1=((x_pos-1)-0.5)*Dx
xx2=(x_pos-0.5)*Dx
yy1=((y_pos-1))*Dy
yy2=(y_pos)*Dy
v1=v[y_pos-1,x_pos-1]
v2=v[y_pos-1,x_pos]
v3=v[y_pos,x_pos-1]
v4=v[y_pos,x_pos]
v_int(Y,X)=(1/(Dx*Dy))*((x2-X)*(y2-Y)*v1+(X-x1)*(y2-Y)*v2+(x2-X)*(Y-y1)*v3+(X-x1)*(Y-y1)*v4)
#PLOT#
function stream(Y,X)
u_c=u_int(Y,X)
v_c=v_int(Y,X)
return u_c,v_c
end
using CairoMakie
let
fig = Figure(resolution = (600, 400))
ax = Axis(fig[1, 1], xlabel = "x", ylabel = "y", backgroundcolor = :black)
streamplot!(ax, stream, -2 .. 4, -2 .. 2, colormap = Reverse(:plasma),
gridsize = (32, 32), arrow_size = 10)
display(fig)
end;
Any solution?
If you know other method with other package, pls tell me.
I am learning how to create plots with slider bars. Here is my code based off the first example of this tutorial
using Plots
gr()
using GLMakie
function plotLaneEmden(log_delta_xi=-4, n=3)
fig = Figure()
ax = Axis(fig[1, 1])
sl_x = Slider(fig[2, 1], range = 0:0.01:4.99, startvalue = 3)
sl_y = Slider(fig[1, 2], range = -6:0.01:0.1, horizontal = false, startvalue = -2)
point = lift(sl_x.value, sl_y.value) do n, log_delta_xi
Point2f(n, log_delta_xi)
end
plot(n, 1 .- log_delta_xi.^2/6, linecolor = :green, label="n = $n")
xlabel!("ξ")
ylabel!("θ")
end
plotLaneEmden()
When I run this, it gives UndefVarError: plot not defined. What am I missing here?
It looks like you are trying to mix and match Plots.jl and Makie.jl. Specifically, the example from your link is entirely for Makie (specifically, with the GLMakie backend), while the the plot function you are trying to add uses syntax specific to the Plots.jl version of plot (specifically including linecolor and label keyword arguments).
Plots.jl and Makie.jl are two separate and unrelated plotting libraries, so you have to pick one and stick with it. Since both libraries export some of the same function names, using both at once will lead to ambiguity and UndefVarErrors if not disambiguated.
The other potential problem is that it looks like you are trying to make a line plot with only a single x and y value (n and log_delta_xi are both single numbers in your code as written). If that's what you want, you'll need a scatter plot instead of a line plot; and if that's not what you want you'll need to make those variables vectors instead somehow.
Depending on what exactly you want, you might try something more along the lines of (in a new session, using only Makie and not Plots):
using GLMakie
function plotLaneEmden(log_delta_xi=-4, n=3)
fig = Figure()
ax = Axis(fig[1, 1], xlabel="ξ", ylabel="θ")
sl_x = Slider(fig[2, 1], range = 0:0.01:4.99, startvalue = n)
sl_y = Slider(fig[1, 2], range = -6:0.01:0.1, horizontal = false, startvalue = log_delta_xi)
point = lift(sl_x.value, sl_y.value) do n, log_delta_xi
Point2f(n, 1 - log_delta_xi^2/6)
end
sca = scatter!(point, color = :green, markersize = 20)
axislegend(ax, [sca], ["n = $n"])
fig
end
plotLaneEmden()
Or, below, a simple example for interactively plotting a line rather than a point:
using GLMakie
function quadraticsliders(x=-5:0.01:5)
fig = Figure()
ax = Axis(fig[1, 1], xlabel="X", ylabel="Y")
sl_a = Slider(fig[2, 1], range = -3:0.01:3, startvalue = 0.)
sl_b = Slider(fig[1, 2], range = -3:0.01:3, horizontal = false, startvalue = 0.)
points = lift(sl_a.value, sl_b.value) do a, b
Point2f.(x, a.*x.^2 .+ b.*x)
end
l = lines!(points, color = :blue)
onany((a,b)->axislegend(ax, [l], ["$(a)x² + $(b)x"]), sl_a.value, sl_b.value)
limits!(ax, minimum(x), maximum(x), -10, 10)
fig
end
quadraticsliders()
ETA: A couple examples closer to what you might be looking for
I have an SCNode which is dynamically created using the SCNPlane geometry to draw a plane using SceneKit.
How do I determine the normal vector to this plane?
Here is a playground demonstrating what I have tried. I have attached a screenshot of the resulting scene that is drawn. I don't think any of the cylinders, which represent the vectors obtained at the normal vector to this red plane.
//: Playground - noun: a place where people can play
import UIKit
import SceneKit
import PlaygroundSupport
// Set up the scene view
let frame = CGRect(
x: 0,
y: 0,
width: 500,
height: 300)
let sceneView = SCNView(frame: frame)
sceneView.showsStatistics = true
sceneView.autoenablesDefaultLighting = true
sceneView.allowsCameraControl = true
sceneView.scene = SCNScene()
// Setup our view into the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 3)
sceneView.scene!.rootNode.addChildNode(cameraNode)
// Add a plane to the scene
let plane = SCNNode(geometry: SCNPlane(width: 3,height: 3))
plane.geometry?.firstMaterial!.diffuse.contents = UIColor.red.withAlphaComponent(0.5)
plane.geometry?.firstMaterial?.isDoubleSided = true
sceneView.scene!.rootNode.addChildNode(plane)
/*
normalSource = [SCNGeometrySource geometrySourceWithData:data
semantic:SCNGeometrySourceSemanticNormal
vectorCount:VERTEX_COUNT
floatComponents:YES
componentsPerVector:3 // nx, ny, nz
bytesPerComponent:sizeof(float)
dataOffset:offsetof(MyVertex, nx)
dataStride:sizeof(MyVertex)];
*/
let dataBuffer = plane.geometry?.sources(for: SCNGeometrySource.Semantic.normal)[0].data
let colorArray = [UIColor.red, UIColor.orange, UIColor.yellow, UIColor.green, UIColor.blue, UIColor.systemIndigo, UIColor.purple, UIColor.brown, UIColor.black, UIColor.systemPink]
let sceneGeometrySource = dataBuffer!.withUnsafeBytes {
(vertexBuffer: UnsafePointer<SCNVector3>) -> SCNGeometrySource in
let sceneVectors = Array(UnsafeBufferPointer(start: vertexBuffer, count: dataBuffer!.count/MemoryLayout<SCNVector3>.stride))
var i=0
for vector in sceneVectors{
let cyl = SCNCylinder(radius: 0.05, height: 3)
cyl.firstMaterial!.diffuse.contents = colorArray[i].withAlphaComponent(0.8)
let lineNode = SCNNode(geometry: cyl)
lineNode.eulerAngles = vector
sceneView.scene!.rootNode.addChildNode(lineNode)
}
return SCNGeometrySource(vertices: sceneVectors)
}
PlaygroundSupport.PlaygroundPage.current.liveView = sceneView
in the apple documentation https://developer.apple.com/documentation/accelerate/working_with_vectors in "Calculate the Normal of a Triangle" you can find the solution. You just need 3 points which are not on one line and then use this:
The following code defines the three vertices of the triangle:
let vertex1 = simd_float3(-1.5, 0.5, 0)
let vertex2 = simd_float3(1, 0, 3)
let vertex3 = simd_float3(0.5, -0.5, -1.5)
Your first step in calculating the normal of the triangle is to create two vectors defined by the difference between the vertices—representing two sides of the triangle:
let vector1 = vertex2 - vertex3
let vector2 = vertex2 - vertex1
The simd_cross function returns the vector that's perpendicular to the two vectors you pass it. In this example, the returned vector is the normal of the triangle. Because the normal represents a direction, you can normalize the value to get a unit vector:
let normal = simd_normalize(simd_cross(vector1, vector2))
I'm trying to draw car trips on a plane. I'm using Plotters library.
Here is some code example of trips' drawing procedure:
pub fn save_trips_as_a_pic<'a>(trips: &CarTrips, resolution: (u32, u32))
{
// Some initializing stuff
/// <...>
let root_area =
BitMapBackend::new("result.png", (resolution.0, resolution.1)).into_drawing_area();
root_area.fill(&WHITE).unwrap();
let root_area =
root_area.margin(10,10,10,10).titled("TITLE",
("sans-serif", 20).into_font()).unwrap();
let drawing_areas =
root_area.split_evenly((cells.1 as usize, cells.0 as usize));
for (index, trip) in trips.get_trips().iter().enumerate(){
let mut chart =
ChartBuilder::on(drawing_areas.get(index).unwrap())
.margin(5)
.set_all_label_area_size(50)
.build_ranged(50.0f32..54.0f32, 50.0f32..54.0f32).unwrap();
chart.configure_mesh().x_labels(20).y_labels(10)
.disable_mesh()
.x_label_formatter(&|v| format!("{:.1}", v))
.y_label_formatter(&|v| format!("{:.1}", v))
.draw().unwrap();
let coors = trip.get_points();
{
let draw_result =
chart.draw_series(series_from_coors(&coors, &BLACK)).unwrap();
draw_result.label(format!("TRIP {}",index + 1)).legend(
move |(x, y)|
PathElement::new(vec![(x, y), (x + 20, y)], &random_color));
}
{
// Here I put red dots to see exact nodes
chart.draw_series(points_series_from_trip(&coors, &RED));
}
chart.configure_series_labels().border_style(&BLACK).draw().unwrap();
}
}
What I got now on Rust Plotters:
So, after drawing it in the 'result.png' image file, I struggle to understand these "lines", because I don't see the map itself. I suppose, there is some way in this library to put a map "map.png" in the background of the plot. If I would use Python, this problem will be solved like this:
# here we got a map image;
img: Image.Image = Image.open("map-image.jpg")
img.putalpha(64)
imgplot = plt.imshow(img)
# let's pretend that we got our map size in pixels and coordinates
# just in right relation to each other.
scale = 1000
x_shift = 48.0
y_shift = 50.0
coor_a = Coordinate(49.1, 50.4)
coor_b = Coordinate(48.9, 51.0)
x_axis = [coor_a.x, coor_b.x]
x_axis = [(element-x_shift) * scale for element in x_axis]
y_axis = [coor_a.y, coor_b.y]
y_axis = [(element-y_shift) * scale for element in y_axis]
plt.plot(x_axis, y_axis, marker='o')
plt.show()
Desired result on Python
Well, that's easy on Python, but I got no idea, how to do similar thing on Rust.
I am having a really hard time trying to visualize some data using f#. I am trying to achieve this on Linux environment using jupyter notebooks that I am running on localhost. I am following this article.
Everything seems to be fine, I managed to load all the needed script files, such as MathNet.Numerics and XPlot. I don't get any errors, my terminal is fine as well, kernel is in place. I wonder why am I not getting any graph reprisentation after I run my code?
It only says that I get back Xplot.Plotly.PlotlyChart, what about the actual graph? I am not sure if this would be enough to help me out, if not, let me know and will fill in other information. I tried different browsers as well, didn't help.
Actual code:
#load #"<project-root>/.paket/load/net45/MathNet.Numerics.fsx"
#load #"<project-root>/.paket/load/net45/MathNet.Numerics.FSharp.fsx"
#load #"<project-root>/.paket/load/net45/XPlot.Plotly.fsx"
open System
open System.Linq
open MathNet.Numerics.Distributions
open MathNet.Numerics.LinearAlgebra
open XPlot.Plotly
let n = 40
let nbsim = 1000
let lambda = 0.2
let randomSeed = 1111
let exponential = Exponential.Samples(new Random(randomSeed), lambda) |> Seq.take (n* nbsim) |> List.ofSeq
let m = Matrix<float>.Build.DenseOfRowMajor(nbsim, n, exponential)
let means = m.RowSums() / (float n)
means.Average()
let historyTrace =
Histogram(
x = means,
xbins =
Xbins(
start = 2.8,
``end`` = 7.75,
size = 0.08
),
marker =
Marker(
color = "yellow",
line =
Line(
color = "grey",
width = 1
)
),
opacity = 0.75,
name = "Exponental distribution"
) :> Trace
let meanTrace =
Scatter(
x = [5; 5],
y = [0; 60],
name = "Theorical mean"
) :> Trace
// Or plain historyTrace below
[historyTrace; meanTrace]
|> Chart.Plot
|> Chart.WithXTitle("Means")
|> Chart.WithYTitle("Frequency")
|> Chart.WithTitle("Distribution of 1000 means of exponential distribution")
Please note that #load statements include <project-root> placeholder. I am using Paket to generate scripts for #load.
This worked for me in the F# Azure Notebook.
Make sure to include this in a cell before you invoke the chart
#load "XPlot.Plotly.Paket.fsx"
#load "XPlot.Plotly.fsx"
open XPlot.Plotly
This is a quote from FSharp for Azure Notebooks:
Note that we had to #load two helper scripts in order to load the
assemblies we need and to enable Display to show our charts. The first
downloads and installs the required Paket packages, and the second
sets up Display support.
The key line for you is: #load "XPlot.Plotly.fsx"
That is the one that lets you display the chart in the notebook.
This is my code in the Azure notebook:
// cell 1
#load "XPlot.Plotly.Paket.fsx"
#load "XPlot.Plotly.fsx"
// cell 2
Paket.Package [ "MathNet.Numerics"
"MathNet.Numerics.FSharp" ]
#load "Paket.Generated.Refs.fsx"
// cell 3
open System
open System.Linq
open MathNet.Numerics.Distributions
open MathNet.Numerics.LinearAlgebra
open XPlot.Plotly
let n = 40
let nbsim = 1000
let lambda = 0.2
let randomSeed = 1111
let exponential = Exponential.Samples(new Random(randomSeed), lambda) |> Seq.take (n* nbsim) |> List.ofSeq
let m = Matrix<float>.Build.DenseOfRowMajor(nbsim, n, exponential)
...