Display struct fields without the mess - octave

I have a struct in Octave that contains some big arrays.
I'd like to know the names of the fields in this struct without having to look at all these big arrays.
For instance, if I have:
x.a=1;
x.b=rand(3);
x.c=1;
The obvious way to take a gander at the structure is as follows:
octave:12> x
x =
scalar structure containing the fields:
a = 1
b =
0.7195967 0.9026158 0.8946427
0.4647287 0.9561791 0.5932929
0.3013618 0.2243270 0.5308220
c = 1
In Matlab, this would appear as the more succinct:
>> x
x =
a: 1
b: [3x3 double]
c: 1
How can I see the fields/field names without seeing all these big arrays?
Is there a way to display a succinct overview (like Matlab's) inside Octave?
Thanks!

You might want to take a look at Basic Usage & Examples. There's several functions mentioned that sound like they'll control the displaying in the terminal.
struct_levels_to_print
print_struct_array_contents
These two functions sound like they're do what you want. I tried both and couldn't get the 2nd one to work. The 1st function changed the terminal output like so:
octave:1> x.a=1;
octave:2> x.b=rand(3);
octave:3> x.c=1;
octave:4> struct_levels_to_print
ans = 2
octave:5> x
x =
{
a = 1
b =
0.153420 0.587895 0.290646
0.050167 0.381663 0.330054
0.026161 0.036876 0.818034
c = 1
}
octave:6> struct_levels_to_print(0)
octave:7> x
x =
{
1x1 struct array containing the fields:
a: 1x1 scalar
b: 3x3 matrix
c: 1x1 scalar
}
I'm running a older version of Octave.
octave:8> version
ans = 3.2.4
If I get a chance I'll check that other function, print_struct_array_contents, to see if it does what you want. Octave 3.6.2 looks to be the latest version as of 11/2012.

Use fieldnames ()
octave:33> x.a = 1;
octave:34> x.b = rand(3);
octave:35> x.c = 1;
octave:36> fieldnames (x)
ans =
{
[1,1] = a
[2,1] = b
[3,1] = c
}
Or you you want it to be recursive, add the following to your .octaverc file (you may want to adjust it to your preferences)
function displayfields (x, indent = "")
if (isempty (indent))
printf ("%s: ", inputname (1))
endif
if (isstruct (x))
printf ("structure containing the fields:\n");
indent = [indent " "];
nn = fieldnames (x);
for ii = 1:numel(nn)
if (isstruct (x.(nn{ii})))
printf ("%s %s: ", indent, nn{ii});
displayfields (x.(nn{ii}), indent)
else
printf ("%s %s\n", indent, nn{ii})
endif
endfor
else
display ("not a structure");
endif
endfunction
You can then use it in the following way:
octave> x.a=1;
octave> x.b=rand(3);
octave> x.c.stuff = {2, 3, 45};
octave> x.c.stuff2 = {"some", "other"};
octave> x.d=1;
octave> displayfields (x)
x: structure containing the fields:
a
b
c: structure containing the fields:
stuff
stuff2
d

in Octave, version 4.0.0 configured for "x86_64-pc-linux-gnu".(Ubuntu 16.04)
I did this on the command line:
print_struct_array_contents(true)
sampleFactorList % example, my nested structure array
Output: (shortened):
sampleFactorList =
scalar structure containing the fields:
sampleFactorList =
1x6 struct array containing the fields:
var =
{
[1,1] = 1
[1,2] =
2 1 3
}
card =
{
[1,1] = 3
[1,2] =
3 3 3
}
To disable/get back to the old behaviour
print_struct_array_contents(false)
sampleFactorList
sampleFactorList =
scalar structure containing the fields:
sampleFactorList =
1x6 struct array containing the fields:
var
card
val
I've put this print_struct_array_contents(true) also into the .octaverc file.

Related

Why are the values ​of the expression not displayed in numeric format?

I have an expression (signal) and I want to get certain results using a loop.
Original formula
Code:
Ak=1.2;
fk=0.0123;
jK=0.321;
alphaK=-0.01;
T=1;
#Signal
#xi=1.2*cos(0,0123*2*pi*(i-1)+0.321)*eps(–0.01*i);
for i=1:4
x(i)=Ak*cos(fk*2*pi*(i-1)+jK)*eps(alphaK*i);
end
The results are in this format
x = 1.9753e-18
x = 1.9753e-18 3.8375e-18
x = 1.9753e-18 3.8375e-18 3.7013e-18
x = 1.9753e-18 3.8375e-18 3.7013e-18 7.0863e-18
But the correct results look like this:
How do I change the format to get the correct display?
replace
x(i)=Ak*cos(fk*2*pi*(i-1)+jK)*eps(alphaK*i);
with
x(i)=Ak*cos(fk*2*pi*(i-1)+jK)*exp(alphaK*i);
and you will have a result much near to the expected one
x =
1.12737 1.08417 1.03531 0.98119
eps is NOT the exponential function
octave:3> eps
ans = 2.2204e-16
octave:4> eps(x)
ans =
2.2204e-16 2.2204e-16 2.2204e-16 1.1102e-16
octave:5> exp(x)
ans =
3.0875 2.9570 2.8160 2.6676

Why octave error with function huffmandeco about large index types?

I've got a little MatLab script, which I try to understand. It doesn't do very much. It only reads a text from a file and encode and decode it with the Huffman-functions.
But it throws an error while decoding:
"error: out of memory or dimension too large for Octave's index type
error: called from huffmandeco>dict2tree at line 95 column 19"
I don't know why, because I debugged it and don't see a large index type.
I added the part which calculates p from the input text.
%text is a random input text file in ASCII
%calculate the relative frequency of every Symbol
for i=0:127
nlet=length(find(text==i));
p(i+1)=nlet/length(text);
end
symb = 0:127;
dict = huffmandict(symb,p); % Create dictionary
compdata = huffmanenco(fdata,dict); % Encode the data
dsig = huffmandeco(compdata,dict); % Decode the Huffman code
I can oly use octave instead of MatLab. I don't know, if there is an unexpected error. I use the Octave Version 6.2.0 on Win10. I tried the version for large data, it didn't change anything.
Maybe anyone knows the error in this context?
EDIT:
I debugged the code again. In the function huffmandeco I found the following function:
function tree = dict2tree (dict)
L = length (dict);
lengths = zeros (1, L);
## the depth of the tree is limited by the maximum word length.
for i = 1:L
lengths(i) = length (dict{i});
endfor
m = max (lengths);
tree = zeros (1, 2^(m+1)-1)-1;
for i = 1:L
pointer = 1;
word = dict{i};
for bit = word
pointer = 2 * pointer + bit;
endfor
tree(pointer) = i;
endfor
endfunction
The maximum length m in this case is 82. So the function calculates:
tree = zeros (1, 2^(82+1)-1)-1.
So it's obvious why the error called a too large index type.
But there must be a solution or another error, because the code is tested before.
I haven't weeded through the code enough to know why yet, but huffmandict is not ignoring zero-probability symbols the way it claims to. Nor have I been able to find a bug report on Savannah, but again I haven't searched thoroughly.
A workaround is to limit the symbol list and their probabilities to only the symbols that actually occur. Using containers.Map would be ideal, but in Octave you can do that with a couple of the outputs from unique:
% Create a symbol table of the unique characters in the input string
% and the indices into the table for each character in the string.
[symbols, ~, inds] = unique(textstr);
inds = inds.'; % just make it easier to read
For the string
textstr = 'Random String Input.';
the result is:
>> symbols
symbols = .IRSadgimnoprtu
>> inds
inds =
Columns 1 through 19:
4 6 11 7 12 10 1 5 15 14 9 11 8 1 3 11 13 16 15
Column 20:
2
So the first symbol in the input string is symbols(4), the second is symbols(6), and so on.
From there, you just use symbols and inds to create the dictionary and encode/decode the signal. Here's a quick demo script:
textstr = 'Random String Input.';
fprintf("Starting string: %s\n", textstr);
% Create a symbol table of the unique characters in the input string
% and the indices into the table for each character in the string.
[symbols, ~, inds] = unique(textstr);
inds = inds.'; % just make it easier to read
% Calculate the frequency of each symbol in table
% max(inds) == numel(symbols)
p = histc(inds, 1:max(inds))/numel(inds);
dict = huffmandict(symbols, p);
compdata = huffmanenco(inds, dict);
dsig = huffmandeco(compdata, dict);
fprintf("Decoded string: %s\n", symbols(dsig));
And the output:
Starting string: Random String Input.
Decoded string: Random String Input.
To encode strings other than the original input string, you would have to map the characters to symbol indices (ensuring that all symbols in the string are actually present in the symbol table, obviously):
>> [~, s_idx] = ismember('trogdor', symbols)
s_idx =
15 14 12 8 7 12 14
>> compdata = huffmanenco(s_idx, dict);
>> dsig = huffmandeco(compdata, dict);
>> fprintf("Decoded string: %s\n", symbols(dsig));
Decoded string: trogdor

How use wikidata api to access to the statements

I'm trying to get information from Wikidata. For example, to access to "cobalt-70" I use the API.
API_ENDPOINT = "https://www.wikidata.org/w/api.php"
query = "cobalt-70"
params = {
'action': 'wbsearchentities',
'format': 'json',
'language': 'en',
'search': query
}
r = requests.get(API_ENDPOINT, params = params)
print(r.json())
So there is a "claims" which gives access to the statements. Is there a best way to check if a value exists in the statement? For example, "cobalt-70" have the value 0.5 inside the property P2114. So how can I check if a value exists in the statement of the entity? As this example.
Is there an approach to access it. Thank you!
I'm not sure this is exactly what you are looking for, but if it's close enough, you can probably modify it as necessary:
import requests
import json
url = 'https://www.wikidata.org/wiki/Special:EntityData/Q18844865.json'
req = requests.get(url)
targets = j_dat['entities']['Q18844865']['claims']['P2114']
for target in targets:
values = target['mainsnak']['datavalue']['value'].items()
for value in values:
print(value[0],value[1])
Output:
amount +0.5
unit http://www.wikidata.org/entity/Q11574
upperBound +0.6799999999999999
lowerBound +0.32
amount +108.0
unit http://www.wikidata.org/entity/Q723733
upperBound +115.0
lowerBound +101.0
EDIT:
To find property id by value, try:
targets = j_dat['entities']['Q18844865']['claims'].items()
for target in targets:
line = target[1][0]['mainsnak']['datavalue']['value']
if isinstance(line,dict):
for v in line.values():
if v == "+0.5":
print('property: ',target[0])
Output:
property: P2114
I try a solution which consists to search inside the json object as the solution proposed here : https://stackoverflow.com/a/55549654/8374738. I hope it can help. Let's give you the idea.
import pprint
def search(d, search_pattern, prev_datapoint_path=''):
output = []
current_datapoint = d
current_datapoint_path = prev_datapoint_path
if type(current_datapoint) is dict:
for dkey in current_datapoint:
if search_pattern in str(dkey):
c = current_datapoint_path
c+="['"+dkey+"']"
output.append(c)
c = current_datapoint_path
c+="['"+dkey+"']"
for i in search(current_datapoint[dkey], search_pattern, c):
output.append(i)
elif type(current_datapoint) is list:
for i in range(0, len(current_datapoint)):
if search_pattern in str(i):
c = current_datapoint_path
c += "[" + str(i) + "]"
output.append(i)
c = current_datapoint_path
c+="["+ str(i) +"]"
for i in search(current_datapoint[i], search_pattern, c):
output.append(i)
elif search_pattern in str(current_datapoint):
c = current_datapoint_path
output.append(c)
output = filter(None, output)
return list(output)
And you just need to use:
pprint.pprint(search(res.json(),'0.5','res.json()'))
Output:
["res.json()['claims']['P2114'][0]['mainsnak']['datavalue']['value']['amount']"]

Extract filenames and ext. from cell array of strings

I want to remove the directory part from a cell array of strings with filenames. Of course one way would be to loop over the cell arrray and use fileparts but I have over 1e5 files and speed really matters.
My current approach is:
fns = {"/usr/local/foo.lib", "~/baz.m", "home/rms/eula.txt", "bar.m"}
filenames = cellfun (#(fn, s) fn(s+1:end), fns,
num2cell (rindex (fns, filesep())),
"UniformOutput", false)
which gives the desired output:
fns =
{
[1,1] = /usr/local/foo.lib
[1,2] = ~/baz.m
[1,3] = home/rms/eula.txt
[1,4] = bar.m
}
filenames =
{
[1,1] = foo.lib
[1,2] = baz.m
[1,3] = eula.txt
[1,4] = bar.m
}
and takes approx 2e-5s per file. Is there a better (faster, more readable) way to do this?
EDIT I've added Sardars solution and my previous attempt with regex and some benchmark results:
fns = {"/usr/local/foo.lib", "~/baz.m", "home/rms/eula.txt", "bar.m"};
fns = repmat (fns, 1, 1e4);
tic
f1 = cellfun (#(fn, s) fn(s+1:end), fns,
num2cell (rindex (fns, "/")),
"UniformOutput", false);
toc
tic
[~, ~, ~, M] = regexp (fns, "[^\/]+$", "lineanchors");
f2 = cell2mat (M);
toc
tic
## Asnwer from Sardar Usama
f3 = regexprep(fns, '.*/', '');
toc
assert (f1, f2)
assert (f1, f3)
which gives
Elapsed time is 0.729995 seconds. (Original code with cellfun)
Elapsed time is 0.67545 seconds. (using regexp)
Elapsed time is 0.230487 seconds. (using regexprep)
Use regexprep to search the strings till the last / and replace the occurrences with an empty string.
filenames = regexprep(fns, '.*/', '');

for every row, reshape and calculate eigenvectors in a vectorized way

I have been wanting to figure this out for a long time, but have had no success yet. I am assuming I will use arrayfun, but I couldn't figure it yet. Appreciate help. Here is the problem:
Given a matrix of many rows and N^2 columns, reshape every row to NxN matrix and calculate eigenvalues, and do this in a vectorized way not using for loop. For example
A=
0.6060168 0.8340029 0.0064574 0.7133187
0.6325375 0.0919912 0.5692567 0.7432627
0.8292699 0.5136958 0.4171895 0.2530783
0.7966113 0.1975865 0.6687064 0.3226548
0.0163615 0.2123476 0.9868179 0.1478827
for every **i**
m=reshape(A(i,:),2,2)
[vc vl]=eig(m)
I am inclined to do something like
f = #(x) eig(reshape(x,2,2))
arrayfun(f,A)
but of course I am getting an error like
octave:5> arrayfun(f,A)
error: reshape: can't reshape 1x1 array to 2x2 array
error: evaluating argument list element number 1
error: evaluating argument list element number 1
error: called from:
error: at line -1, column -1
error: cellfun: too many output arguments
error: /usr/share/octave/3.2.4/m/general/arrayfun.m at line 168, column 21
A = [0.6060168 0.8340029 0.0064574 0.7133187;
0.6325375 0.0919912 0.5692567 0.7432627;
0.8292699 0.5136958 0.4171895 0.2530783;
0.7966113 0.1975865 0.6687064 0.3226548;
0.0163615 0.2123476 0.9868179 0.1478827];
N = 2;
[mc, ml] = arrayfun (#(row) eig (reshape (A (row, :), N, N)), 1:rows(A), "UniformOutput", false)
mc =
{
[1,1] =
-0.170783 -0.044626
0.985309 -0.999004
[1,2] =
-0.95343 -0.89053
0.30161 -0.45492
(cropped)
}
ml =
{
[1,1] =
Diagonal Matrix
0.56876 0
0 0.75057
[1,2] =
Diagonal Matrix
0.45246 0
0 0.92334
(cropped)
With the Ndpar package, calculations can be parallelized over multiple cores.
Borrowing from Andy's answer,
pkg load ndpar
A = [0.6060168 0.8340029 0.0064574 0.7133187;
0.6325375 0.0919912 0.5692567 0.7432627;
0.8292699 0.5136958 0.4171895 0.2530783;
0.7966113 0.1975865 0.6687064 0.3226548;
0.0163615 0.2123476 0.9868179 0.1478827];
N = 2;
[eigenvectors, eigenvalues] = ndpar_arrayfun(nproc,
#(row) eig(reshape(row, N, N)),
A, "IdxDimensions", 1, "Uniformoutput", false)
yields the same output.
EDIT - Or with the original pararrayfun from the octave-forge parallel package:
[eigenvectors, eigenvalues] = pararrayfun(nproc,
#(row_idx) eig(reshape(A(row_idx, :), N, N)),
1:rows(A), "UniformOutput", false)