Mix of regular text and LaTeX in Julia plot title - plot

Tried everything except what works to get the following title in my plot: "Volume in m^3 at threshold=30". The threshold value should come from a variable called threshold.
using Plots
using LaTeXStrings
threshold = 30
plot(1:10)
title!("Volume in \$m^3\$ at threshold=$threshold")
# The following works with a hard-coded value for threshold
title!(#L_str("\\textrm{Volume in }m^3\\textrm{ at threshold=30}"))
# The following fails:
s = "\\textrm{Volume in }m^3\\textrm{ for threshold=$threshold}"
title!(#L_str(s))
Error message:
ERROR: LoadError: MethodError: no method matching
#L_str(::LineNumberNode, ::Module, ::Symbol)
Closest candidates are:
#L_str(::LineNumberNode, ::Module, ::String) at
/home/tarik/.julia/packages/LaTeXStrings/YQ4GM/src/LaTeXStrings.jl:68
in expression starting at REPL[25]:1

OK, figured out a solution by avoiding the L macro that does not seem to do much other than adding a $ sign at the beginning and end of strings.
using Plots
using LaTeXStrings
threshold = 30
s="\$\\textrm{Volume in }m^3\\textrm{ at threshold=$threshold}\$"
plot(1:30)
title!(s)

Related

Error plotting array with exponential operation

I am new to Julia and I am trying to create a plot with the following:
xi2 = range(0,sqrt(6),step=1e-3)
collect(xi2)
plot(xi2, 1-xi2^2/6, label="n = 0")
When I try this though, I have the error:
MethodError: no method matching ^(::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, ::Int64)
Closest candidates are:
^(::Union{AbstractChar, AbstractString}, ::Integer) at C:\Users\Acer\AppData\Local\Programs\Julia-1.7.0\share\julia\base\strings\basic.jl:721
^(::Rational, ::Integer) at C:\Users\Acer\AppData\Local\Programs\Julia-1.7.0\share\julia\base\rational.jl:475
^(::Complex{<:AbstractFloat}, ::Integer) at C:\Users\Acer\AppData\Local\Programs\Julia-1.7.0\share\julia\base\complex.jl:839
...
What am I missing here?
You want the elements of xi2 raised to the power of two, so you want element-wise operations using the dot operator:
julia> xi2 = range(0,sqrt(6),step=1e-3);
julia> plot(xi2, 1 .- xi2.^2/6, label="n = 0")
(The collect step was unnecessary, since most array operations can be performed on a range directly. And in case you did want to collect - i.e. allocate memory and make it a full array - you have to assign the result of collect to some variable. In your original code, the elements were being collected into an array, but then thrown away since the result wasn't assigned to anything.)

Values of ket vectors in Julia

I can't figure out how to get specific elements/ values of a ket vector in Julia language. I tried to call a specific index of the ket vector using [index], like one does with a regular vector, but that does not seem to work with kets.
Kets are available in the QuantumOptics.jl package. So for a simple example, if I would define a ket myself:
basis = FockBasis(2)
x = Ket(basis, [1,3,2])
which gives output:
Ket(dim=3)
basis: Fock(cutoff=2)
1.0
3.0
2.0
If I then try to get an element of the ket, I would try it like this:
x[1]
which gives an error:
MethodError: no method matching getindex(::Ket{FockBasis{Int64},Array{Int64,1}}, ::Int64)
and I can't access the seperate elements of the ket.
Maybe the easiest way to get the j coefficient for a ket is just to access the j value for the data property of the ket. For your example you can just do
j = 1
j_coeff = x.data[j]

Complex numbers in R vs. Matlab

I observed the following phenomenon when using R and Matlab.
When I apply log to a negative number in R, I get the following error message:
Warning message:
In log(-1) : NaNs produced
However, when I apply log to a negative number in Matlab, I get e.g., the following complex numbers:
log(-1): 0.0000 + 3.1416i
log(-5): 1.6094 + 3.1416i
Is there any way to achieve the same behavior in R? Or is there anything in favor of the default option in R?
log gives you complex when you give it complex in the first place.
log(-1+0i)
# [1] 0+3.141593i
log(-5+0i)
# [1] 1.609438+3.141593i
I don't know why it doesn't give an option to do this by default, but then again I don't work in complex numbers all the time.
If you want to do this programmatically, you can use as.complex:
log(as.complex(-1))
# [1] 0+3.141593i
or even make a helper function simplify it for you:
mylog <- function(x, ...) log(as.complex(x), ...)
mylog(-1)
# [1] 0+3.141593i

How to tell R how to plot objects of a certain class?

I'm currently dealing with some objects that are a list of attributes that represents a statistical model. For example, let's say I have a matrix, a numeric vector and an integer.
myobj = list(amatrix = matrix(1:9,3,3),avector = c(1:3),aninteger = 1)
class(myobj) = 'myclass'
Suppose that, for some reason, I can create a plot that represents an object of this class. How can I make plot(myobj) recognizes that the object has the class 'myclass', and print it in the desired way, for example image(myobj$amatrix)?
I think the question is essentially how to 'modify' R's plot function so it knows how to handle a newly defined object class? Can I use functions of other packages like ggplot when executing this modification?
In a more general sense, how does functions that handle different classes of objects know how to act for each class?
I have little to none experience with classes in R, so even some simple guides about classes should be helpful.
As mentionned by #emilliman you can define your own method:
myobj = list(amatrix = matrix(1:9,3,3),avector = c(1:3),aninteger = 1)
class(myobj) <- 'myclass'
plot.myclass <- function(x) image(x$amatrix)
methods(plot) # check the 4th element of 3rd line :) (list will differ depending on what packages are loaded)
# [1] plot.acf* plot.data.frame* plot.decomposed.ts* plot.default plot.dendrogram* plot.density* plot.ecdf
# [8] plot.factor* plot.formula* plot.function plot.hclust* plot.histogram* plot.HoltWinters* plot.isoreg*
# [15] plot.lm* plot.medpolish* plot.mlm* plot.myclass plot.ppr* plot.prcomp* plot.princomp*
# [22] plot.profile.nls* plot.R6* plot.raster* plot.spec* plot.stepfun plot.stl* plot.table*
# [29] plot.ts plot.tskernel* plot.TukeyHSD*
#and plot :
plot(myobj)

unexpected "=" in par=c(...)

I'm trying to reproduce the following code (nls function does not perform well), but with an extra implementation, using for loops, sprintf and as.formula(), that adds variables depending of the number of peaks in the given spectrum. To be more coherent among peaks, I vectorized the variable names for each peak, so peak number 1 has 'alfa[1]', 'peak[1]' and 'height[1]' related to it.
So far, I got the expected formula:
height[1]/(pi*alfa[1]*(1+((x-peak[1])/alfa[1])^2))+height[2]/(pi*alfa[2]*(1+((x-peak[2])/alfa[2])^2))+drift.a+drift.b*x
Nevertherless, I have some problems when I try to replicate the same system for the par line. This should show:
par=c(alfa[1]=0.001,
peak[1]=2.156460,
height[1]=1,
alfa[2]=0.001,
peak[2]=2.170150,
height[2]=1,
drift.a=0,
driftb=0)
But instead, when I collapse all strings and used the as.formula command afterwards, I got:
Error en parse(text = x) : <text>:1:15: unexpected '='
1: par=c( alfa[1]=
^
If I print the collapsed string, the character line is the one expected, so I'm thinking that it will be somehow linked to the as.formula command (i.e. it may not be the appropiated command)
When you create a named vector using c, the names must be valid variable names, or you have to wrap them in quotes.
This is OK:
c(alfa1 = 0.001)
## alfa1
## 0.001
alfa[1] is not a valid variable name – it's the first element of a variable – so you have to wrap it in quotes:
c(alfa1[1] = 0.001)
## Error: unexpected '=' in "c(alfa1[1] ="
c("alfa1[1]" = 0.001)
## alfa1[1]
## 0.001
Backquotes also work:
c(`alfa1[1]` = 0.001)
## alfa1[1]
## 0.001
See also is_valid_variable_name in the assertive package.
library(assertive)
is_valid_variable_name(c("alfa1", "alfa[1]"))
## alfa1 alfa[1]
## TRUE FALSE
You can turn your coefficient names into valid variable names using make.names:
make.names("alfa[1]")
## [1] "alfa.1."
You want to have vectors like alfa and so on to store several values, if I understand you correctly. Maybe you should try to combine this vectors in a list, this makes them more accessible.
And it should be a good idea to name this list not par.
As far as I understand your question, you have more than one peak to process. So you have data like:
peak <- c(2.31, 3.17, ...)
alfa <- c(0.001, 0.002, ...)
In this case, you could use list(peak = peak, ...) to construct a list with all your parameters and then call your function and supply appropriate objects from the list.
Or did I missed the main point of your question?

Resources