Scrambling an array in idl - idl-programming-language

I was wondering if there is a module in idl that one can use to scramble an array of floating point numbers. I tried using scramble.pro but the problem is that it returns integers, and if I try to use float it doesn't return the exact numbers i entered, for example:
array = [2.3, 4.5, 5.7,8.9]
scr_array = scramble(array)
print, scr_array
output:
4 2 8 5
and if i use float:
print, float(scr_array)
the output is:
4.0000 2.0000 8.0000 5.0000
Any ideas?

Try using this sampling routine, but asking for all the elements:
IDL> array = [2.3, 4.5, 5.7,8.9]
IDL> scramble_indices = mg_sample(4, 4)
IDL> print, scramble_indices
1 3 0 2
IDL> print, array[scramble_indices]
4.50000 8.90000 2.30000 5.70000

scramble.pro assumes that the input is an integer array, so it always gives an integer array as its output. You can, however, use it to generate a random ordering of indices and feed these back into your original array (like mgalloy has done with mg_sample):
IDL> array = [2.3, 4.5, 5.7,8.9]
IDL> scr_array = array[scramble(n_elements(array))]
IDL> print, scr_array
8.90000 2.30000 5.70000 4.50000
Here, scramble is given a single integer value, so it creates the random indices required. For vanilla IDL only, I often use the randomu and sort functions in combination to get the same effect:
IDL> array = [2.3, 4.5, 5.7,8.9]
IDL> indices = sort(randomu(seed, n_elements(array)))
IDL> scr_array = array[indices]
IDL> print, indices
3 2 0 1
IDL> print, scr_array
8.90000 5.70000 2.30000 4.50000
Here, we're using randomu to generate a set of random numbers with the same number of elements as array, and sort gives us the indices that would put that random array in order. Together, they give you a random ordering of indices. Of course, you can put that on a single line too:
IDL> array = [2.3, 4.5, 5.7,8.9]
IDL> scr_array = array[sort(randomu(seed, n_elements(array)))]
IDL> print, scr_array
5.70000 2.30000 8.90000 4.50000

Related

how to convert multidimensional array to string in idl

I have an array of floats or doubles lets call it foo. When I do
size(foo)
I get these 5 dimensions
2 67 52100 4 3498338
I would like to convert it to a string like
str="strcture={arr:"+foo+"}"
so that I can then do
Execute(str)
How can I convert foo to a string dynamically?
I have something to print the declaration of a variable in my library:
IDL> print, mg_variable_declaration(replicate({a: 0.0, b: 1.0}, 10))
replicate({ A: 0.00000, B: 1.00000 }, 10)
It won't get all the data values, though. Just create a variable of the correct type. It might get you part of the way, though.

Julia - Reshaping an array according to a vector

I have an array of arrays, a
49455-element Array{Array{AbstractString,1},1}
the length varies, this is just one of many possibilities
I need to do a b = vcat(a...) giving me
195158-element Array{AbstractString,1}:
and convert it to a SharedArray to have all cores work on the strings in it (I'll convert to a Char matrix behind the curtians, but this is not important)
In a, every element is an array of some number of strings, which I do
map(x -> length(x), a)
49455-element Array{Int64,1}:
1
4
8
.
.
2
Is there a way I can easily resotre the array b to the same dimensions of a?
With the Iterators.jl package:
# `a` holds original. `b` holds flattened version. `newa` should == `a`
using Iterators # install using Pkg.add("Iterators")
lmap = map(length,a) # same length vector defined in OP
newa = [b[ib+1:ie] for (ib,ie) in partition([0;cumsum(lmap)],2,1)]
This is somewhat neat, and can also be used to produce a generator for the original vectors, but a for loop implementation should be just as fast and clear.
As a complement to Dan Getz's answer, we can also use zip instead of Iterators.jl's partition:
tails = cumsum(map(length,a))
heads = [1;tails+1][1:end-1]
newa = [b[i:j] for (i,j) in zip(heads,tails)]

String SHA1 in Julia

I have an ordered set of points (x,y pairs) I would like to use as a key in a dictionary.
My original approach in ruby was to get a string representation of the points and then SHA1 the results.
What would be the best way to accomplish this in Julia?
Edit:
The key that I want to create is the set of points, not the individual points within the set.
I have a process that creates a set of unique integer points and I want to see if I have encountered this particular set of points before. I also want to store some information about this particular set of points. For example how many times have I seen this configuration.
The length of the set of points varies between 20 and 180ish.
With a SHA1 hash of the string representation of these points I know that my key is going to be 40 characters long regardless of the length of the points.
In effect I'm using SHA1 to compress my key to keep the size of my dictionary as small as I can. I would like this dictionary to grow to a fairly large size.
You can just use the points them directly as keys of a dictionary, e.g.
points = [(rand(),rand()) for i in 1:100]
a_dict = [p => rand(1:10000) for p in points]
#show points[1]
#show a_dict[points[1]]
produces
points[1] => (0.4374267407775083,0.32232663537074036)
a_dict[points[1]] => 4102
EDIT: The question is asking about lists of points rather than single pairs. Its hard to tell from your question, but if you wanted to throw out the lists of points, then I'd just use the hash function, which is what a dictionary uses:
julia> x = [(rand(),rand()) for i in 1:100];
julia> y = copy(x);
julia> z = [(rand(),rand()) for i in 1:100];
julia> hash(x)
0x2dd258e3af0ec93a
julia> hash(y)
0x2dd258e3af0ec93a
julia> hash(z)
0x6449b750e42e6bc6
julia> some_dict = [hash(x) => 1, hash(z) => 1]
Dict{Uint64,Int64} with 2 entries:
0x6449b750e42e6bc6 => 1
0x2dd258e3af0ec93a => 1
julia> if hash(y) in keys(some_dict)
some_dict[hash(y)] += 1
else
some_dict[hash(y)] = 1
end
julia> some_dict
Dict{Uint64,Int64} with 2 entries:
0x6449b750e42e6bc6 => 1
0x2dd258e3af0ec93a => 2
If you actually need to retrieve what the sets of points are though, which seems likely, then you can just use a dictionary directly with the set of points as the key, i.e.
julia> other_dict = [x=>1,z=>1]
Dict{Array{(Float64,Float64),1},Int64} with 2 entries:
[(0.6453074757765922,0.0958215… => 1
[(0.5283378708792779,0.8418390… => 1
julia> other_dict[y] += 1
2
julia> other_dict
Dict{Array{(Float64,Float64),1},Int64} with 2 entries:
[(0.6453074757765922,0.0958215… => 1
[(0.5283378708792779,0.8418390… => 2
This (using mutable keys) is perfectly fine in Julia (although bad things will happen if you change the keys of dictionary once they've been added, of course).

Multidimensional Array Comprehension in Julia

I'm mucking about with Julia and can't seem to get multidimensional array comprehensions to work. I'm using a nightly build of 0.20-pre for OSX; this could conceivably be a bug in the build. I suspect, however, it's a bug in the user.
Lets say I want to wind up with something like:
5x2 Array
1 6
2 7
3 8
4 9
5 10
And I don't want to just call reshape. From what I can tell, a multidimensional array should be generated something like: [(x, y) for x in 1:5, y in 6:10]. But this generates a 5x5 Array of tuples:
julia> [(x, y) for x in 1:5, y in 6:10]
5x5 Array{(Int64,Int64),2}:
(1,6) (1,7) (1,8) (1,9) (1,10)
(2,6) (2,7) (2,8) (2,9) (2,10)
(3,6) (3,7) (3,8) (3,9) (3,10)
(4,6) (4,7) (4,8) (4,9) (4,10)
(5,6) (5,7) (5,8) (5,9) (5,10)
Or, maybe I want to generate a set of values and a boolean code for each:
5x2 Array
1 false
2 false
3 false
4 false
5 false
Again, I can only seem to create an array of tuples with {(x, y) for x in 1:5, y=false}. If I remove the parens around x, y I get ERROR: syntax: missing separator in array expression. If I wrap x, y in something, I always get output of that kind -- Array, Array{Any}, or Tuple.
My guess: there's something I just don't get here. Anybody willing to help me understand what?
I don't think a comprehension is appropriate for what you're trying to do. The reason can be found in the Array Comprehension section of the Julia Manual:
A = [ F(x,y,...) for x=rx, y=ry, ... ]
The meaning of this form is that F(x,y,...) is evaluated with the variables x, y, etc. taking on each value in their given list of values. Values can be specified as any iterable object, but will commonly be ranges like 1:n or 2:(n-1), or explicit arrays of values like [1.2, 3.4, 5.7]. The result is an N-d dense array with dimensions that are the concatenation of the dimensions of the variable ranges rx, ry, etc. and each F(x,y,...) evaluation returns a scalar.
A caveat here is that if you set one of the variables to a >1 dimensional Array, it seems to get flattened first; so the statement that the "the result is... an array with dimensions that are the concatenation of the dimensions of the variable ranges rx, ry, etc" is not really accurate, since if rx is 2x2 and ry is 3, then you will not get a 2x2x3 result but rather a 4x3. But the result you're getting should make sense in light of the above: you are returning a tuple, so that's what goes in the Array cell. There is no automatic expansion of the returned tuple into the row of an Array.
If you want to get a 5x2 Array from a comprhension, you'll need to make sure x has a length of 5 and y has a length of 2. Then each cell would contain the result of the function evaluated with each possible pairing of elements from x and y as arguments. The thing is that the values in the cells of your example Arrays don't really require evaluating a function of two arguments. Rather what you're trying to do is just to stick two predetermined columns together into a 2D array. For that, use hcat or a literal:
hcat(1:5, 6:10)
[ 1:5 5:10 ]
hcat(1:5, falses(5))
[ 1:5 falses(5) ]
If you wanted to create a 2D Array where column 2 contained the result of a function evaluated on column 1, you could do this with a comprehension like so:
f(x) = x + 5
[ y ? f(x) : x for x=1:5, y=(false,true) ]
But this is a little confusing and it seems more intuitive to me to just do
x = 1:5
hcat( x, map(f,x) )
I think you are just reading the list comprehension wrong
julia> [x+5y for x in 1:5, y in 0:1]
5x2 Array{Int64,2}:
1 6
2 7
3 8
4 9
5 10
When you use them in multiple dimensions you get two variables and need a function for the cell values based on the coordinates
For your second question I think that you should reconsider your requirements. Julia uses typed arrays for performance and storing different types in different columns is possible. To get an untyped array you can use {} instead of [], but I think the better solution is to have an array of tuples (Int, Bool) or even better just use two arrays (one for the ints and one for the bool).
julia> [(i,false) for i in 1:5]
5-element Array{(Int64,Bool),1}:
(1,false)
(2,false)
(3,false)
(4,false)
(5,false)
I kind of like the answer #fawr gave for the efficiency of the datatypes while retaining mutability, but this quickly gets you what you asked for (working off of Shawn's answer):
hcat(1:5,6:10)
hcat({i for i=1:5},falses(5))
The cell-array comprehension in the second part forces the datatype to be Any instead of IntXX
This also works:
hcat(1:5,{i for i in falses(5)})
I haven't found another way to explicitly convert an array to type Any besides the comprehension.
Your intuition was to write [(x, y) for x in 1:5, y in 6:10], but what you need is to wrap the ranges in zip, like this:
[i for i in zip(1:5, 6:10)]
Which gives you something very close to what you need, namely:
5-element Array{(Int64,Int64),1}:
(1,6)
(2,7)
(3,8)
(4,9)
(5,10)
To get exactly what you're looking for, you'll need:
hcat([[i...] for i in zip(1:5, 6:10)]...)'
This gives you:
5x2 Array{Int64,2}:
1 6
2 7
3 8
4 9
5 10
This is another (albeit convoluted) way:
x1 = 1
x2 = 5
y1 = 6
y2 = 10
x = [x for x in x1:x2, y in y1:y2]
y = [y for x in x1:x2, y in y1:y2]
xy = cat(2,x[:],y[:])
As #ivarne noted
[{x,false} for x in 1:5]
would work and give you something mutable
I found a way to produce numerical multidimensional arrays via vcat and the splat operator:
R = [ [x y] for x in 1:3, y in 4:6 ] # make the list of rows
A = vcat(R...) # make n-dim. array from the row list
Then R will be a 3x3 Array{Array{Int64,2},2} while A is a 9x2 Array{Int64,2}, as you want.
For the second case (a set of values and a Boolean code for each), one can do something like
R = [[x y > 5] for x in 1:3, y in 4:6] # condition is y > 5
A = vcat(R...)
where A will be a 9x2 Array{Int64,2}, where true/false is denote by 1/0.
I have tested those in Julia 0.4.7.

Allocate array from array of sizes

Let's say I have an array of dimensions declared like this:
integer, dimension(5) :: dims
dims = (/ 5, 6, 7, 8, 9 /)
How can I most simply use this array to allocate another array, using the elements of dims to specify the size of the respective dimensions? Say the second array is declared like this:
real, dimension(:,:,:,:,:), allocatable :: dset
Why can't I do the following?
allocate (dset(dims(:)))
I get Error: Rank mismatch in array reference when I attempt to compile.
I realize that I can do this:
allocate (dset(dims(1), dims(2), dims(3), dims(4), dims(5)))
But I'm looking for something more easily extensible.
You cannot write allocate(dset(dims(:))) for exactly the reason the compiler gives: they have different ranks. If you were to print shape(dims), you would see 5 on-screen; if you were to print shape(dset), you would see either 0 0 0 0 0 or 5 6 7 8 9 (depends if you allocated it or not); dims is a rank-1 array, dset is a rank-5 array.
So pretty much the only way to allocate an allocatable is via the explicit method that you feel is inextensible.

Resources