bugGNU Octave - Bugs: bug #47904, text() with the wrong sized vector...

 
 

bug #47904: text() with the wrong sized vector or cell array gives unexpected/weird results

Submitter:  None
Submitted:  Thu 12 May 2016 01:10:35 AM UTC
   
 
Category:  Plotting Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Matlab Compatibility
Status:  Fixed Assigned to:  None
Originator Name:  Peter Halasz Originator Email:  -email is unavailable-
Open/Closed:  * Closed Release:  * 4.0.2
Operating System:  * Any Fixed Release:  None
Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Sat 21 May 2016 06:00:49 AM UTC, comment #7: 

Thanks everyone for the test results.  I've made a fix on the development branch here (http://hg.savannah.gnu.org/hgweb/octave/rev/31b4b614ed55).  Closing report.

Rik <rik5>
Group administrator
Fri 20 May 2016 07:29:48 PM UTC, comment #6: 

Matlab R2015b

test 1:

>> x = 1:5;
>> y = 1:5;
>> plot (x, y, 'o');
>> labels1 = {'a', 'b', 'c', 'd'};
>> text (x,y,labels1)
Error using text
Each string specified must have a corresponding set of coordinates

plot appeared, image attached as comment5_test1.png

after test 2:

>> clf;
>> plot (x, y, 'o');
>> labels2 = {'a', 'b', 'c', 'd', 'e'};
>> text (x,y,labels2)

plot appeared, image attached as comment5_test2.png

after test 3:

>> clf;
plot (x, y, 'o');
labels3 = ['a'; 'b'; 'c'; 'd'];
text (x,y,labels3)
Error using text
Each string specified must have a corresponding set of coordinates

plot appeared, image attached as comment5_test3.png


after test 4:

>> clf;
plot (x, y, 'o');
labels4 = ['a'; 'b'; 'c'; 'd'; 'e'];
text (x,y,labels4)
>>

plot appeared, image attached as comment5_test4.png



Nicholas Jankowski <nrjank>
Group Member
Fri 20 May 2016 07:25:48 PM UTC, comment #5: 

Here the output of Matlab R2016a

First test:


>> x = 1:5;
>> y = 1:5;
>> plot (x, y, 'o');
>> labels1 = {'a', 'b', 'c', 'd'};
>> text (x,y,labels1)
Error using text
Each string specified must have a corresponding set of coordinates


"I believe this will create a 4-row column of labels at every point." - No.

Second test:


>> clf;
>> plot (x, y, 'o');
>> labels2 = {'a', 'b', 'c', 'd', 'e'};
>> text (x,y,labels2)


"I believe this will create a single label at each point." - Yes.

Third test:


>> clf;
>> plot (x, y, 'o');
>> labels3 = ['a'; 'b'; 'c'; 'd'];
>> text (x,y,labels3)
Error using text
Each string specified must have a corresponding set of coordinates


"Maybe it is supposed to error out." - Yes.

Fourth test:


>> clf;
>> plot (x, y, 'o');
>> labels4 = ['a'; 'b'; 'c'; 'd'; 'e'];
>> text (x,y,labels4)


"I believe thiss will create a single label at each point as in the second test." - Yes

Kai Torben Ohlhus <siko1056>
Group Member
Fri 13 May 2016 12:06:28 AM UTC, comment #4: 

Can someone run the following code under Matlab and report back?

First test:


x = 1:5;
y = 1:5;
plot (x, y, 'o');
labels1 = {'a', 'b', 'c', 'd'};
text (x,y,labels1)


I believe this will create a 4-row column of labels at every point.

Second test:


clf;
plot (x, y, 'o');
labels2 = {'a', 'b', 'c', 'd', 'e'};
text (x,y,labels2)


I believe this will create a single label at each point.

Third test:


clf;
plot (x, y, 'o');
labels3 = ['a'; 'b'; 'c'; 'd'];
text (x,y,labels3)


No idea what this will do.  Maybe it is supposed to error out.

Fourth test:


clf;
plot (x, y, 'o');
labels4 = ['a'; 'b'; 'c'; 'd'; 'e'];
text (x,y,labels4)


I believe thiss will create a single label at each point as in the second test.


Rik <rik5>
Group administrator
Thu 12 May 2016 10:17:07 PM UTC, comment #3: 

I'm the one who re-wrote most of text.m to get it close to Matlab compatibility.  It was very difficult, hence the note I left at the top of the code:


## Note: The following code is rigged for Matlab compatibility and is
##       full of hidden assumptions.  Be very wary when modifying.


I have absolutely no ego with someone else modifying this code.  However, make sure you test, test, TEST the final m-file to make sure compatibility with Matlab hasn't been broken.

I agree that Octave should, at the very least, produce an error for the case of 500 points and 499 labels.

The slow plotting speed for scatter has been reported before.  See bug #40663.  It turns out not to be a trivial problem to solve.

To convert between a cell array of strings and a 2-D character matrix use the function char().


Rik <rik5>
Group administrator
Thu 12 May 2016 03:41:08 AM UTC, comment #2: 

According to xixor on #octave,


Error using text
Each string specified must have a corresponding set of coordinates


is the error Matlab throws for a mismatched number of (x,y) coordinates and labels. So yes, we should also throw an error in that situation.

Mike Miller <mtmiller>
Group Member
Thu 12 May 2016 02:54:03 AM UTC, comment #1: 

Confirming the combinatorial problem when the number of (x,y) points does not match the number of text strings.

On my laptop with Debian:


ttext = 500x2 char label data. Time: 1.616
ttext = 500x1 cell label data. Time: 1.611
ttext = 499x2 char label data. Time: 1.557
ttext = 499x1 cell label data. Time: 4.550


I think we can consider it a known issue that plotting performance on Windows is not ideal, I'd call that a separate issue than the one of mismatching text arguments.

I don't know if this is avoidable, the Matlab help is (as usual) ambiguous. They definitely show that a single point with a cell array of strings is interpreted as multiple lines of text. And a cell array with multiple points is interpreted as a different label for each point. But they do not give the example of say, 3 (x,y) coordinates and a cell array of length 2. I'd like to think that would be an error.

Anyone with Matlab care to test?

https://www.mathworks.com/help/matlab/ref/text.html

Mike Miller <mtmiller>
Group Member
Thu 12 May 2016 01:10:35 AM UTC, original submission:  

In my experience, filing a long or detailed bug report leads to fewer people reading or responding to it, so I've including a TL;DR for the lazy.

TL;DR: see attached screenshots. There's little I've said below that isn't summed up in the first screenshot.

I'm relatively new to Octave, but I was encouraged to report this when I was helped on IRC. I'm not experienced enough to demand Octave's behaviour is changed, but I can give you an idea of the experience which seems very suboptimal.

I made a minimal example and duplicated it four times with minimal changes to show a comparison of different configurations. You can run it once at see three random scatter plots with slightly different inputs.

The first subplot is 500 random points with 500 text labels, given as a 500x2 char vector (vector of strings). The 'x2' is because 2 characters is the max length of a label in this example. Renders correctly.

The second is also 500 random points with 500 text labels, but this time given as a cell array (500x1). Renders correctly.

The third is 500 random points with 499 text labels (to simulate an "off by one" user error). Text data is given as a vector of strings (char 499x2). This causes the first label text to be used for all labels, and the others to be ignored. This behaviour seems kinda weird. Perhaps it's acceptable to do this without a warning? I don't know.

The forth is 500 random points with 499 text labels, given as a cell array (499x1). This causes all 499 labels to be rendered for every one of the 500 points. This takes around 20 seconds to render on Windows (i7 2600 / GTX 460). This might be expectedly slow for Octave, but it is a performance issue, it's difficult to debug the off-by-one user error because of the performance issue, and it's very weird/unexpected behaviour even if it is vaguely documented to do this (though I'm not sure if it is).

The code:


numberOfPoints = 500;

x = rand(numberOfPoints, 1);
y = rand(numberOfPoints, 1);
l = rand(numberOfPoints, 1) .* 10; # label data
labels = int2str(l);
cellLabels = cellstr(labels);

figure

subplot(1,4,1)
start = time();
scatter(x, y);
text(x, y, labels);
t = num2str(time()-start, '%1.3f');
ttext = ['500x2 char label data. Time: ' t]
title(ttext);

subplot(1,4,2)
start = time();
scatter(x, y);
text(x, y, cellLabels);
t = num2str(time()-start, '%1.3f');
ttext = ['500x1 cell label data. Time: ' t]
title(ttext);

subplot(1,4,3)
start = time();
scatter(x, y);
text(x, y, (labels(2:end, :))); # Oops! One label missing
t = num2str(time()-start, '%1.3f');
ttext = ['499x2 char label data. Time: ' t]
title(ttext);

subplot(1,4,4)
start = time();
scatter(x, y);
text(x, y, (cellLabels(2:end, :))); # Oops! One label missing
t = num2str(time()-start, '%1.3f');
ttext = ['499x1 cell label data. Time: ' t]
title(ttext);


A screenshot is attached of the output (awful_text_example_4_subplots.png).

The text output of the code (required, as one title is obscured in the screenshot):


ttext = 500x2 char label data. Time: 4.399
ttext = 500x1 cell label data. Time: 4.393
ttext = 499x2 char label data. Time: 4.414
ttext = 499x1 cell label data. Time: 19.461


Some might say the output is expected and desired, but I'll steam roll ahead and offer some suggestions to make the user experience better. Perhaps the community could come up with something which better matches how Octave does things and allows better backwards compatibility with existing code bases. Mostly I hope this bug report might be a launching point for discussion which motivates someone to develop Octave's code base further and make it a better open source product.

Recommended fixes:

1. At a minimum: Display a warning to the user if there is a mismatch between the number of labels and the number of data points when calling text(), unless there is only one label and it is only one line in length.

2. Change the behaviour of text() so it treats cell arrays similarly to vector arrays. i.e. create some consistency, although both behaviours seem bad when there are mismatched input lengths.

3. Implement a separate function (or require an additional parameter) to render the same lines of text multiple times (as what is currently default for cell data), or to force data to be ignored (as what is currently default for vector of strings input)

Those seem like the obvious answers, but perhaps the community could come up with and agree to a better solution.

More general recommendations:

4. Improve rendering times. I don't know anything about the internals of Octave's rendering engine, but I can't see why the first three examples should take 4+ seconds to render. Coming from a game development background, drawing 500 anti-aliased circles with 2-character labels should take microseconds, not seconds. If rendering times were improved, then debugging would become easier. Removing 20 seconds from the debug cycle allows more experimentation by the user. (See "Motivation / background" below for how this directly impacted my debugging of this)

5. Use a separate thread to respond quickly to user input. Closing the "Figure 1" window should not take 20 seconds (as you wait for it to finish rendering). And the software should not appear to be hung just because because you resized a window.

6. Display an "Executing..." message with a barber's pole or something to tell the user a script is still running and hasn't crashed.

7. Implement the table data type and readtable(), e.g. bug #44571 -- my initial bug would have been unlikely to come up if I was importing data in a uniform way. Instead I hacked together a couple of different methods to import the text and numeric data from a CSV.

8. Prevent subplots from rendering outside of their area. I would have liked to present my examples on a 2x2 subplot grid. :)

Motivation / background:

I was trying to draw a scatter plot of some CSV data I had generated elsewhere. I'd accidentally left the heading row in some of the data and it created a monstrosity (see real_world_example.png). When I was initially trying to debug my code, as I didn't know the problem, I just saw a lot of text filling up my scatter plot. So I reduced the number of labels from 512 to just 50 so it would render fast enough that I could debug. Doing that also cut down the clutter enough that I could see what it was actually going on (all labels being rendered at all points). At some point I fixed the off-by-one mismatch, but as I had cut down the number of labels being displayed, the weird rendering continued. I assumed it was the data format of labels. I went onto #octave to ask how to convert cells to a string array. IRC user jwe asked the right questions and pointed out the size mismatch of the data, and then encouraged me to file this bug report. I still don't know how to convert cell data to a vector of strings. Thanks for reading. I hope this bug report encourages you to work on improving Octave.

Anonymous

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #37215:  comment5_test1.png added by nrjank (6KiB - image/png)
file #37216:  comment5_test3.png added by nrjank (6KiB - image/png)
file #37217:  comment5_test2.png added by nrjank (7KiB - image/png)
file #37218:  comment5_test4.png added by nrjank (7KiB - image/png)
file #37135:  real_world_example.png added by None (243KiB - image/png)
file #37134:  awful_text_example_4_subplots.png added by None (838KiB - image/png)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by nrjank (Updated the item)
  • -email is unavailable- added by siko1056 (Posted a comment)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by mtmiller (Posted a comment)
  • -email is unavailable- added by None (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 12 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2016-05-21 rik5 StatusConfirmed Fixed
        Open/ClosedOpen Closed
    2016-05-20 nrjank Attached File- Added comment5_test1.png, #37215
        Attached File- Added comment5_test3.png, #37216
        Attached File- Added comment5_test2.png, #37217
        Attached File- Added comment5_test4.png, #37218
    2016-05-12 mtmiller StatusNeed Info Confirmed
    2016-05-12 mtmiller Item GroupOther Matlab Compatibility
        StatusNone Need Info
        Operating SystemMicrosoft Windows Any
    2016-05-12 None Attached File- Added awful_text_example_4_subplots.png, #37134
        Attached File- Added real_world_example.png, #37135

    Back to the top

    Powered by Savane 3.13-caa5.
    Corresponding source code