visible_when with multiple logical tests - enthought

In TraitsUI, for an Item(), is it possible to setup a visible_when() parameter list with more than 1 item?
For example, I'd like something like this:
Group(
Item(FirstItem, visible_when = 'foo == 1 and bar == 0'),
Item(SecondItem, visible_when = 'foo == 0 and bar == 1),
Item(ThirdItem, visible_when = 'foo == 0 and bar == 0)
)
So that only FirstItem, SecondItem, or ThirdItem would show up based on the values in foo and bar.
Is this possible? I've made an initial attempt, but had no luck (which may be because one of my logic tests involves a string -- is my problem having a string test inside the visible_when string? This is what my visible_when test looks like (and isn't working):
visible_when = 'Initial_value == 1 && display_units == \'SI\'',
I've tried with the SI in double quotes "SI" and with the escaped single quotes as above...neither worked for me.
I've also tried using 'and' and '&&' with no difference either.

Yes, multiple tests work. To verify this, run a slightly modified https://raw.githubusercontent.com/enthought/traitsui/master/examples/demo/Dynamic_Forms/visible_when.py, where you change, for example, the two visible_when conditions to these:
visible_when = 'age < 18 and last_name=="Smith"',
and
visible_when = 'age >= 18 or last_name!="Smith"',
I suggest checking assumptions about data contents.
(BTW, strings can use either with either double or escaped single quotes -- I suggest double quotes for readability)

Related

Variables, expressions, and `if` statement

I have few similar questions about expressions. I marked them as Q1, Q2 and Q3 for convenience.
First. As stated in the docs,
Variable names in an expression are not enclosed in percent signs (except for pseudo-arrays and other double references). Consequently, literal strings must be enclosed in double quotes to distinguish them from variables.Source
As I understand, this means we should write code like this:
a = aaa
b = zzz
if (a = "aaa" or b = "bbb")
MsgBox, It works!
However, this seems also works:
a = aaa
b = zzz
if (%a% = aaa or %b% = bbb)
MsgBox, It works!
Is there some drawbacks in the second way? (Q1)
One possible drawback, which I found myself, is that second method will not work if variable contains only digits. This will not work:
a = 111
b = 999
if (%a% = 111 or %b% = 222)
MsgBox, It works!
Why it stopped worked now? (Q2)
And also, if variable contains only digits, there seems no need to quote it's value in expression:
a = 111
if (a = "111") ; Also works for a = "aaa"
MsgBox, It works!
a = 111
if (a = 111) ; It will not work for a = "aaa". We forced to us quote signs if var contains letters.
MsgBox, It works too.
Why second way (if (a = 111)) works and should or should not we avoid it? (Q3).
(Q1)
If a variable is enclosed in percent signs within an expression (in your example %a%), whatever that variable contains is assumed to be the name or partial name of another variable.
This also works
a = aaa
b = zzz
if (%a% = a or %h% = cc)
MsgBox, It works!
because the values of the vars %a% and %h% are not specified.
(Q2)
If both var and value are purely numeric, they will be compared as numbers rather than as strings.
Otherwise, they will be compared alphabetically as strings (that is, alphabetical order will determine whether var is greater, equal, or less than value).
(Q3)
Only literal strings must be enclosed in double quotes.
If the variable contains only digits, there is no need to quote.

delete NA in some rows in matlab

I have some rows in a text file have NA and i want to delete them .
when i used isempty(strfind(l,'NA')), this deletes also strings have NA such as: 'RNASE' ,'GNAS'
example
0.552353744371678 NA
0.0121476193502138 ANG;RNASE
0.189489997218949 GNAS
0.0911820441646675 MYCL1
output:
0.0911820441646675 MYCL1
output expected:
0.0121476193502138 ANG;RNASE
0.189489997218949 GNAS
0.0911820441646675 MYCL1
Using single regexp I do not know how to find
"NA that does not have any alphanumeric character before or after".
I mean, it is easy if you know there will be at least one other character before and after:
ind = regexp(str, '[^A-Za-z_]NA[^A-Za-z_]'); %Or something similar, depending what exactly can and cannot be there.
However, this string requires characters before and after and will not match single 'NA' by itself.
That is to say, I am nearly certain suitable regexp exists, I just don't know it :)
What I would do is (assuming strl = single line with text you are deciding to keep or remove, that might have multiple NA).
ind = regexp(strl, 'NA'); % This finds all NA in the string.
removestr = true;
for i = 1 : length(ind)
if (ind == 1 || any(regexp(strl(ind-1), '[^A-Za-z_]'))) ... &&
&& (ind+1 == length(strl) || any(regexp(strl(ind+2), '[^A-Za-z_]')))
disp('This is maybe the string to remove - if there are no wrong NA's later')
else
removestr = false;
break; % stop checking in this loop, this string is to keep.
end
end
if (removestr)
disp('Remove string')
end
Conditions in if are a bit overkill and quite slow, but should work. If you don't require checking for multiple NA in a single line, simply omit for loop.

perl how to force boolean to 0/1

I'm trying to get a 0 or 1 in a value for true/false. Here's the code:
use strict;
my %h = (Y => "y");
my $bool_x = 1 & exists $h{X};
my $bool_y = 1 & exists $h{Y};
print("x $bool_x y $bool_y\n");
I needed to add the "1 &" to force it to not be the empty string. Is there a better way to do this? I realize that it's an artifact of the way perl prints the false value, but I need it to be a 0 not the empty string.
The most efficient way to do this is just:
$bool || 0
Your code is far from clear. The & operator is a bitwise operator that behaves differently on numbers and strings, but exists returns a value that will obligingly be the number zero or the empty string depending on what is required of it. perldoc perlop has this to say
Although no warning is currently raised, the result is not well defined when this operation is performed on operands that aren't either numbers (see Integer Arithmetic) nor bitstrings (see Bitwise String Operators)
So because the result of exists is one such value your code is on shakey ground
There is no need to write something arcane, and if you want to represent Perl's internal true and false values by a different pair of values then the conditional operator is the correct choice
my $bool_x = exists $h{X} ? 1 : 0
I believe that's the most readable without being verbose, and that's all that matters here. It's also applicable to any other pair of values that you may choose, such as
my $bool_x = exists $h{X} ? 'Y' : 'N'
There are many ways to "numify" a true/false value.
If $var can contain 1 or any false value, all of these will evaluate to either "0" or "1":
0 + $var
0 | $var
$var || 0
1 * $var
1 & $var (you discovered this one, already)
chr(48+$var)
sprintf "%d", $var
These constructions return a 0/1 value when $var can contain any true or false value:
0 + !!$var ( !! true => 1, !! false => "" )
1 - !$var
$var ? 1 : 0

perl script for find and replace or insert if blank

I am trying to write a perl script to search a config file for the following line:
remote_phonebook.data.1.url =
and do 1 of 2 things:
if the right of side of the = is blank add someString
if there is something there, replace anything there with someString
This will insert just fine:
s/remote_phonebook\.data\.1\.url = /remote_phonebook.data.1.url = someString/;
however if someString already exists, it will append it to look like this:
remote_phonebook.data.1.url = someString someString
This will replace just fine if someString already exists, but wont insert if its blank.
s/remote_phonebook\.data\.1\.url = someString/remote_phonebook.data.1.url = someString/;
.* is your friend, here. It means "match 0 or more (*) of any character (.)":
s/remote_phonebook\.data\.1\.url =.*/remote_phonebook.data.1.url = someString/;
So whether or not there is anything after the =, you'll end up with the contents you want. To make sure that you're matching from the start of the line (so "xxxremote_phonebook..." won't match), and to allow for more (or less) space before the "=", I'd use:
s/^remote_phonebook\.data\.1\.url\s*=.*/remote_phonebook.data.1.url = someString/;
s/^\s*remote_phonebook\.data\.1\.url\s*=\K.*/someString/;
The .* will match anything up to a newline.
The \K makes it so you don't have to repeat everything.

How to determine whether a string represents an integer?

I need to determine if a string contains just an integer. The built-in function isinteger is not working.
To avoid loops I'd like to apply this task on cell arrays of strings.
For example:
Q = { 'qf5' ; '4' ; 'true' ; 'false' ; '4.00' ; '4E0' ; '4e0' ; '657' };
desired result:
integers = 0 1 0 0 0 0 0 1
For a single string I figured out an ugly workaround, but I can't imagine that this is the only possible way, and also it requires a loop to use it on cell arrays:
myString = '4';
integer = uint64( str2double( myString ) );
newString = int2str( integer );
isStringInteger = strcmp(newString,myString);
Which essential function am I missing?
You can do it with regexp; and to avoid the loop you use cellfun:
~cellfun('isempty', regexp(Q, '^-?\d+$'))
This considers an "integer" as a string of digits, possibly with one minus sign at the beginning.
Note that cellfun with the builtin function 'isempty' is very fast.
Well, the string is not an integer, therefore the question as such is not correct. What you want to check is whether the string is a representation of an integer. The isinteger function is also not what you want, because it does not check whether the actual content of a numeric variable is an integer, but whether the data type is an integer type.
As far as I can tell, there is no built-in way to check whether a string represents an integer. One approach to implement such a check would be to see whether all the characters in the string represent digits:
isintstr = all(myString >= '0') && all(myString <= '9')
This code takes advantage of the fact that the decimal digits are encoded in sequence in ASCII and Unicode.
To allow for leading and trailing white space, use
isintstr = all(strtrim(myString) >= '0') && all(strtrim(myString) <= '9')