Julia - console behaving differently than include("myfile.jl") - julia

I would like to execute the following code, which works perfectly well when I type every line into my Julia console on Windows 10, but throws an error because of the mismatching type LinearAlgebra.Adjoint{Float64,Array{Float64,2}} (my subsequent code expects Array{Float64,2}).
This is the code:
x = [0.2, 0.1, 0.2]
y = [-0.5 0.0 0.5]
fx = x * y
fy = fx'
return fx::Array{Float64,2}, fy::Array{Float64,2}
There is a TypeError, because fy seems to be of type LinearAlgebra.Adjoint{Float64,Array{Float64,2}} instead of Array{Float64,2}.
How can I do a transpose and get a "normal" Array{Float64,2} object ?
And why does this work when I type every line into my Julia console, but does not when I run the file via include("myfile.jl") ?

Use collect to have a copy of actual data rather than a transformed view of the original (note that this rule applies to many other similar situations):
julia> x = [0.2, 0.1, 0.2];
julia> y = [-0.5 0.0 0.5];
julia> fx = x * y
3×3 Array{Float64,2}:
-0.1 0.0 0.1
-0.05 0.0 0.05
-0.1 0.0 0.1
julia> fy = fx'
3×3 LinearAlgebra.Adjoint{Float64,Array{Float64,2}}:
-0.1 -0.05 -0.1
0.0 0.0 0.0
0.1 0.05 0.1
julia> fy = collect(fx')
3×3 Array{Float64,2}:
-0.1 -0.05 -0.1
0.0 0.0 0.0
0.1 0.05 0.1

To get a normal Matrix{Float64} use:
fy = permutedims(fx)
or
fy = Matrix(fx')
Those two are not 100% equivalent in general as fx' is a recursive adjoint operation (conjugate transpose), while permutedims is a non-recursive transpose, but in your case they will give the same result.
What does recursive adjoint mean exactly?
recursive: the conjugate transpose is applied recursively to all entries of the array (in your case you have array of numbers and transpose of a number is the same number so this does not change anything);
adjoint: if you would have complex numbers then the operation would return their complex conjugates (in your case you have real numbers so this does not change anything);
Here is an example when both things matter:
julia> x = [[im, -im], [1-im 1+im]]
2-element Array{Array{Complex{Int64},N} where N,1}:
[0+1im, 0-1im]
[1-1im 1+1im]
julia> permutedims(x)
1×2 Array{Array{Complex{Int64},N} where N,2}:
[0+1im, 0-1im] [1-1im 1+1im]
julia> Matrix(x')
1×2 Array{AbstractArray{Complex{Int64},N} where N,2}:
[0-1im 0+1im] [1+1im; 1-1im]
However, unless you really need to you do not have to do it if you really need to get a conjugate transpose of your data. It is enough to change type assertion to
return fx::Array{Float64,2}, fy::AbstractArray{Float64,2}
or
return fx::Matrix{Float64}, fy::AbstractMatrix{Float64}
Conjugate transpose was designed to avoid unnecessary allocation of data and most of the time this will be more efficient for you (especially with large matrices).
Finally the line:
return fx::Array{Float64,2}, fy::Array{Float64,2}
throws an error also in the Julia command line (not only when run from a script).

Related

Julia equivalent of Python numpy "arange"

In Python, I can create an array of evenly spaced values using
xi2 = np.arange(0, np.sqrt(6), 1e-3)
How do I write this in Julia? I tried,
xi2 = range(0,sqrt(6),step=1e-3)
but this returns 0.0:0.001:2.449
The result, 0.0:0.001:2.449 is indeed a range of evenly spaced values, and can be indexed, sliced, broadcasted on, and generally used just like any other AbstractArray. For example:
julia> xi2 = range(0,sqrt(6),step=1e-3)
0.0:0.001:2.449
julia> xi2[1]
0.0
julia> xi2[100]
0.099
julia> length(xi2)
2450
julia> isa(xi2, AbstractArray)
true
julia> sin.(xi2)
2450-element Vector{Float64}:
0.0
0.0009999998333333417
0.0019999986666669333
0.002999995500002025
⋮
0.6408405168240852
0.6400725224915994
0.6393038880866445
0.6385346143778549
If for any reason you want to turn xi2 into a full Array preemptively, you can do that with collect
julia> collect(xi2)
2450-element Vector{Float64}:
0.0
0.001
0.002
0.003
⋮
2.446
2.447
2.448
2.449
which will "materialize" the range, so to speak. This uses a lot more memory than the Range though, and is less often necessary than you might expect.

How to fill missing values in a loop using conditions in julia?

I would like to check the loop for number of items and then if the items are of not expected size then fill it with 0's. For example, I have created a loop which tries to access an array's elements for a range of 10
x = range(1, 100, length=45) |> collect
n = trunc(Int, length(x)/10) + 1
s = 1
l = 10
for i in 1:n
print(x[s:l])
s += 10
l +=10
end
In the above code, last iteration doesn't print any result as the number of elements are only 5 but it expects it to be 10. Hence, I would like to know, how may i check in this loop for every iteration the number of elements and if they are not expected then fill it with 0's.
Please suggest and advise on achieving the expected operation.
Thanks!
I think that PaddedViews is what you are looking for:
julia> using PaddedViews
julia> PaddedView(0, x, (ceil(Int, length(x)/10)*10,))
50-element PaddedView(0.0, ::Vector{Float64}, (Base.OneTo(50),)) with eltype Float64:
1.0
3.25
5.5
7.75
10.0
12.25
14.5
16.75
⋮
97.75
100.0
0.0
0.0
0.0
0.0
0.0

How to create two nested for loops in a single line in Julia

I have seen it a few times where someone has a situation where they want to put two for loops on the same line nested in one another.
Just to confirm, is this possible in Julia and if so what does it look like? Thanks!
Correct, Julia allows you to tersely express nested for loops.
As an example, consider filling in a 3x3 matrix in column order:
julia> xs = zeros(3,3)
3×3 Array{Float64,2}:
0.0 0.0 0.0
0.0 0.0 0.0
0.0 0.0 0.0
julia> let a = 1
for j in 1:3, i in 1:3
xs[i,j] = a
a += 1
end
end
julia> xs
3×3 Array{Float64,2}:
1.0 4.0 7.0
2.0 5.0 8.0
3.0 6.0 9.0
The above loop is equivalent to this more verbose version:
julia> let a = 1
for j in 1:3
for i in 1:3
xs[i,j] = a
a += 1
end
end
end
This syntax is even supported for higher dimensions(!):
julia> for k in 1:3, j in 1:3, i in 1:3
#show (i, j, k)
end

Perspective warp an image in Julia

I have an image and a 3x3 perspective projection matrix M. How do I apply the transform on the image?
I tried to use the warp(img, tform) function but don't know how to construct the transform object from the matrix.
Tried tform = PerspectiveMap() ∘ inv(LinearMap(M)), no idea if this is a correct to create the transform, but it fails with:
ERROR: Inverse transformation for CoordinateTransformations.PerspectiveMap has not been defined.
There are two components to the answer:
You have to define a transformation that takes a 2-vector to a 2-vector
If the transformation isn't invertible, then you have to specify the range of indices of the final image manually.
For the first, the following suffices:
julia> using StaticArrays, CoordinateTransformations
julia> M = #SMatrix [1 0 0; 0 1 0; -1/1000 0 1] # a 3x3 perspective transformation matrix
3×3 StaticArrays.SArray{Tuple{3,3},Float64,2,9}:
1.0 0.0 0.0
0.0 1.0 0.0
-0.001 0.0 1.0
julia> tform = PerspectiveMap() ∘ inv(LinearMap(M))
(CoordinateTransformations.PerspectiveMap() ∘ LinearMap([1.0 0.0 0.0; -0.0 1.0 0.0; 0.001 -0.0 1.0]))
julia> tform(#SVector([1,1,1])) # this takes a 3-vector as input and returns a 2-vector
2-element SVector{2,Float64}:
0.999001
0.999001
julia> push1(x) = push(x, 1)
push1 (generic function with 1 method)
julia> tform2 = PerspectiveMap() ∘ inv(LinearMap(M)) ∘ push1 # here's one that takes a 2-vector as input (appends 1 to the 2-vector)
(::#55) (generic function with 1 method)
julia> tform2(#SVector([1,1]))
2-element SVector{2,Float64}:
0.999001
0.999001
Now let's try this on an image. We'll create an output image that has the same indices as the input image, although you can choose any indices you want:
julia> using Images, TestImages
julia> img = testimage("lighthouse");
julia> imgw = warp(img, tform2, indices(img)); # 3rd argument sets the indices
julia> using ImageView
julia> imshow(imgw)
img looks like this:
and imgw looks like this:

error with vectorized function in Julia: "arrays could not be broadcast to a common size"

I get an error when trying to evaluate the following function in Julia (Version 0.3.11, 2015-07-27 06:18 UTC, LinuxMint Rebecca):
# this_script.jl
# global parameters
c = [ 1.0 , 2.0]
u = [-1.0 , 3.5]
# A simplified version of a more complicated function
function f(x,y)
xi = c .* (x/y - u)
1.0 + sum( erfi(xi) )
end
#vectorize_2arg Number f
I can evaluate things like f(2,1), f(2+im,1), or
x=linspace(-2,2,4);
f(x,x)
y=rand(4,4)
f(y,y)
However, the following lines throw an error:
u=repmat(x,1,4)
f(u,u)
ERROR: arrays could not be broadcast to a common size
in broadcast_shape at broadcast.jl:40
in .* at broadcast.jl:278
in f at operators.jl:377
in include at ./boot.jl:245
in include_from_node1 at ./loading.jl:128
while loading this_script.jl, in expression starting on line 103
After that, I cannot evaluate f anymore even with f(2,1) nor f(x,x). Notice that u and y have the same dimensions and type.
How can I handle this?
The problem is that you've updated u to be 4x4, but c is still a two element vector.
julia> c,u
([1.0,2.0],
4x4 Array{Float64,2}:
-2.0 -2.0 -2.0 -2.0
-0.666667 -0.666667 -0.666667 -0.666667
0.666667 0.666667 0.666667 0.666667
2.0 2.0 2.0 2.0 )
julia> c.*(1/2-u)
ERROR: DimensionMismatch("arrays could not be broadcast to a common size")
(As an aside, note that globals like c and u can be a performance trap unless they're marked as const.)

Resources