Generation of plot legend names in GNU Octave - octave

I would like to generate the legends of a plot in GNU Octave, based on how many lines I plot, how do I do this?
The names of each legend should be the same except a number in the name.
Here is what i do now:
W = 3
data = zeros(W, 1000);
% Calculate data...
plot(data.');
legend("w1", "w2", "w3");
The problem arises when I change W to some other value, then i have to manually update the legend call with more or less strings.

for i=1:W
leg(i,:)=strjoin({"W",int2str(i)},"");
endfor
legend(leg)

You can specify the name of the line in the plot command, through the DisplayName line property. legend will use these names:
clf; hold on
plot(data(1,:), 'DisplayName','w1');
plot(data(2,:), 'DisplayName','w2');
legend;

Related

Extrapolate two columns from txt with commas and text

I got a problem reading some data from a txt file. I appreciate any suggestion and thank you in advance!
I have a txt file with text/number on top, followed by two tab-separated columns (additionally, they have commas instead of dots).
I want to extract the two columns without text, and replace the commas with dots in order to plot them.
I tried with importdata to be able to replace the commas, but it separates every single character, so I get 36k elements instead of 2048.
Tried dlmread but it ignores the second column...
I have no idea how to proceed without modifying every single file manually.
here is an example of the file:
Data from FLMS012901__118__10-30-26-589.txt Node
Date: Tue Jul 05 10:30:26 CEST 2022
User: Myself
Number of Pixels in Spectrum: 2048
>>>>>Begin Spectral Data<<<<<
338,147 -2183,94
338,527 -2183,94
338,906 -2183,94
339,286 -2251,25
Any suggestions?
EDIT:
Apparently, there was already a solution, even though a bit slow:
% Read file in as a series of strings
fid = fopen('data.txt', 'rb');
strings = textscan(fid, '%s', 'Delimiter', '');
fclose(fid);
% Replace all commas with decimal points
decimal_strings = regexprep(strings{1}, ',', '.');
% Convert to doubles and join all rows together
data = cellfun(#str2num, decimal_strings, 'uni', 0);
data = cat(1, data{:});
On the sample that you provide, the following works:
>> [a,b,c,d] = textread("SO_73502149.txt","%f,%f %f,%f", "headerlines", 6);
>> format free
>> [a+b/1000, c+sign(c).*d/100]
ans =
338.147 -2183.94
338.527 -2183.94
338.906 -2183.94
339.286 -2251.25
However there are some possible traps, according to the way decimal figures are handled in your file, you should adapt the post-processing: If for 338.10 338,1 is printed in the file instead of 338,10 , the decoding would be a bit harder. Whenever c becomes zero, sign(c) would kill the decimal part. A less trivial post-processing would be required.

Solving linear equation by matrix method in Octave

I was writing a code to solve linear equations by matrix method. This is my code
A=input('Enter the coeffecient matrix A: ');
B=input('Enter the constant matrix B (column matrix form): ');
A
B
X=['x'; 'y'; 'z'];
R=inv(A)*B;
disp('Result');
R
This is what I did. But I want to get Output result to displayed in the form of
Matrix(X)=Matrix(R) so that people could directly compare the values of variables in Matrix (X) with Matrix (R) . It may very easy one but however I tried I am not getting it. How could I implement this ?
How about
prettyprint(R,["x";"y";"z"]," ")
Or you can add a column header instead of a blank character.
This function requires the econometrics package, so if you don't have that, first do
pkg install -forge econometrics
pkg load econometrics
I actually solved it by adding the code
for i=[1:1:3];
printf('%s = %f \n',X(i,:),R(i,:))
end

Julia Box plots, not reading columns where the csv file column that the name has spaces and parenthesis but has no problem reading 1word column title

So here's the code in Julia
using CSV
using DataFrames
using PlotlyJS
df= CSV.read("path", DataFrame)
plot(df, x=:Age, kind="box")
#I DO get the box plot for this one, because in the csv that column is headed with "Age"
plot(df, x=:Annual Income (k$), kind="box")
ERROR: syntax: missing comma or ) in argument list
Stacktrace:
[1] top-level scope
# none:1
#here I get an error asking about syntax, but I don't understand since the x= part is exactly what the column is labeled. If I try 'x=:Annual' I get a box plot of nothing, but the column title is "Annual Income (k$)".
Help is greatly appreciated!
Refrence: https://plotly.com/julia/box-plots/
Try:
plot(df, x=Symbol("Annual Income (k\$)"), kind="box")
The : syntax constructs a Symbol, but only upto the next space. So :Annual Income (k$) says to build the Symbol Symbol("Annual"), but then leaves the Income (k$) parts dangling. Instead you can explicitly construct the Symbol yourself like above.
The backslash before the $ symbol is because Julia uses $ usually for interpolation, and here we want to use the raw $ character itself. You can also do plot(df, x=Symbol(raw"Annual Income (k$)"), kind="box") instead, as no interpolation happens inside raw"" strings.

How to replace MATLAB's timeseries and synchronize functions in Octave?

I have a MATLAB script that I would like to run in Octave. But it turns out that the timeseries and synchronize functions from MATLAB are not yet implemented in Octave. So my question is if there is a way to express or replace these functions in Octave.
For understanding, I have two text files with different row lengths, which I want to synchronize into one text file with the same row length over time. The content of the text files is:
Text file 1:
1st column contains the distance
2nd column contains the time
Text file 2:
1st column contains the angle
2nd column contains the time
Here is the part of my code that I use in MATLAB to synchronize the files.
ts1 = timeseries(distance,timed);
ts2 = timeseries(angle,timea);
[ts1 ts2] = synchronize(ts1,ts2,'union');
distance = ts1.Data;
angle = ts2.Data;
Thanks in advance for your help.
edit:
Here are some example files.
input distance
input roation angle
output
The synchronize function seems to create a common timeseries from two separate ones (here, specifically via their union), and then use interpolation (here 'linear') to find interpolated values for both distance and angle at the common timepoints.
An example of how to achieve this to get the same output in octave as your provided output file is as follows.
Note: I had to preprocess your input files first to replace 'decimal commas' with dots, and then 'tabs' with commas, to make them valid csv files.
Distance_t = csvread('input_distance.txt', 1, 0); % skip header row
Rotation_t = csvread('input_rotation_angle.txt', 1, 0); % skip header row
Common_t = union( Distance_t(:,2), Rotation_t(:,2) );
InterpolatedDistance = interp1( Distance_t(:,2), Distance_t(:,1), Common_t );
InterpolatedRotation = interp1( Rotation_t(:,2), Rotation_t(:,1), Common_t );
Output = [ InterpolatedRotation, InterpolatedDistance ];
Output = sortrows( Output, -1 ); % sort according to column 1, in descending order
Output = Output(~isna(Output(:,2)), :); % remove NA entries
(Note, The step involving removal of NA entries was necessary because we did not specify we wanted extrapolation during the interpolation step, and some of the resulting distance values would be outside the original timerange, which octave labels as NA).

Octave: Box and whisker plot without spread from GeoTIFF

---- Update with what I got so far and what's left to resolve can be found in point 3 below ----
Using Octave I want to create 30 horizontal box and whisker plots without spread (x-axis) from 30 different GeoTIFF's. This is a sketch of how I would like the plot to look like:
Ideally the best solution for me would be an Octave code (workflow) that would allow me to place multiple GeoTIFFs in one directory and then with one click create a box and whisker plot for all GeotIFFs at once - just like the sketch above.
A GeoTIFF-sample with 3 GeoTIFF's can be downloaded here. The file looks like this in QGIS:
It holds elevation values on band 1 (the ones that each box and whisker plot should be based on, and no data values (-999), the no-data values should be excluded from the plot.
Right now this is what I got:
Using img = imread ("filname.tif") gets the file into Octave. Using hist (img(:), 200); shows that all cells are concentrated around 65300. imagesc (img, [65100 65600]) follwed by colorbar displays the image extent but's it's clear that this way simply doesn't import the real cell values. I can't find a working solution to import GeoTIFF's with cell values, therefor my current work-around is exporting the GeoTIFF from QGIS with gdal_translate -of aaigrid which creates a .asc-file that I manually edit to remove header rows, rename to .csv and load into Octave. That .csv can be found here.
To load it and create a box plot I'm currently using this code (thanks to #Andy and #Cris Luengo):
pkg load statistics
s = urlread ("https://drive.google.com/uc?export=download&id=1RzJ-EO0OXgfMmMRG8wiCBz-51RcwSM5h");
o = str2double (strsplit (s, ";"));
o(isnan (o)) = [];
boxplot (o)
set(gca,"xtick",[])
view([-90 90])
print out.png
The results is pretty close but I'm still failing to: A) load GeoTIFF's directly from a folder. If this is not possible I'm gonna have to modify the code to load all *.csv in a directory to the same box plot and label each plot by filename (which I'm unsure how to accomplish. B) to get the x-axis reversed (going from 200-450, not the other way around). This is caused by the view([-90 90]) that I use to make the box plot horizontal instead of vertical which is needed for layout reasons.
Anyone with any ideas on how to resolve the last adjustments?
---- Background info ----
I have 30 GeoTIFFs containing results from a viewshed analysis, for every 2x2 meter square there is a value the tells me how high a building can be (in meters) before it's visible from the viewshed point. The results cover the whole city of Stockholm but the above mentioned 30 GeoTIFFs are smaller clips of an area where new development is planned. The results help planners to understand how new development might effect each of the 30 places (that are important for cultural heritage management).
As part of a bigger PDF-report (where these results are visualized with different maps in different scales) I'm trying to produce a box and whisker plot (as a compliment to the maps) the gives the reader an overview over how much space is there is left at the planned development area, based on each of the 30 viewshed (GeoTIFF) results (one box and whisker for each of the 30 locations). Below is an example of how a map in the report can look like:
Does not directly read GeoTIFF but calls gdal_translate under the hood. Just place all your .tif in the same directory. Make sure gdal_translate is in your PATH:
pkg load statistics
clear all;
fns = glob ("*.tif");
for k=1:numel (fns)
ofn = tmpnam;
cmd = sprintf ('gdal_translate -of aaigrid "%s" "%s"', fns{k}, ofn);
[s, out] = system (cmd);
if (s != 0)
error ('calling gdal_translate failed with "%s"', out);
endif
fid = fopen (ofn, "r");
# read 6 headerlines
hdr = [];
for i=1:6
s = strsplit (fgetl (fid), " ");
hdr.(s{1}) = str2double (s{2});
endfor
d = dlmread (fid);
# check size against header
assert (size (d), [hdr.nrows hdr.ncols])
# set nodata to NA
d (d == hdr.NODATA_value) = NA;
raw{k} = d;
# create copy with existing values
raw_v{k} = d(! isna (d));
fclose (fid);
endfor
## generate plot
boxplot (raw_v)
set (gca, "xtick", 1:numel(fns),
"xticklabel", strrep (fns, ".tif", ""));
view ([-90 90])
zoom (0.95)
print ("out.png")
gives