Using 2 different outputs of 'return' of a function in separate elements of a plot - function

I am drawing a plot of voltage per time. For the voltage values, I want the values to be evaluated by a 'scaling' function which converts the values from volts to kilovolts if the biggest element is higher than 1000 volts (11000 volts to 11 KILOvolts).
This function is supposed to return 2 separate outputs; one for (new) values of voltage and one for the unit. The values are fed into the y axis values of the plot and the unit is given to the labeling line of that axis. For example:
import numpy as np
time = np.array([0, 1, 2, 3])
system_voltage1 = np.array([110, 120, 130, 150])
system_voltage2 = np.array([11000, 12000, 13000, 15000])
scaling_function(input)
if np.amax(input) < 1000:
output = input/1
Voltage_label = 'Voltage in Volts'
if np.amax(input) > 1000:
output = input/1000
Voltage_label = 'Voltage in KILOVolts'
return(output, Voltage_label)
fig14 = plt.figure(figsize=(16,9))
ax1 = fig14.add_subplot(111)
l1, = ax1.plot(time, scaling_function(system_voltage), color='r')
ax1.set_xlabel("time in second", color='k')
ax1.set_ylabel(Voltage_label, color='k')
Now, I am having trouble, calling this function properly. I need the function to only receive the output for scaling_function(system_voltage), and receive Voltage_label in ax1.set_ylabel(Voltage_label, color='k'). Now:
A) My problem: I don't know how to write the code so only the first output is received and used for scaling_function(system_voltage) , and the second element for the labeling line.
B) Something I tried but didn't work:Voltage_label does not recognize the value of voltage_label from scaling_function, as it is located in an outer loop than the function. I mean, I cannot access voltage_label as its value is not globally assigned.
Can anyone help me with this?

y,l = scaling_function(system_voltage)
l1, = ax1.plot(time, y, color='r')
ax1.set_xlabel("time in second", color='k')
ax1.set_ylabel(l, color='k')

Related

How to define a default vector/matrix for a function's input

I would like to create a function in which one of the inputs is a matrix. But I also want the function to have a default input. For example, please see the following simple "test" function with an input "x":
def test(x=None):
if x==None:
y = np.array([[123], [123]])
else:
y = x
return y
In this way, let's say I want to see the function without providing input:
print(test())
Would give:
[[123]
[123]]
However, if I want "x" to be a matrix or vector (like the following script):
z = np.array([[12], [12]])
print(test(z)
I got an error saying:
**"The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()".**
Fine, I want to comply with the error warning. Then I changed the function to:
def test(x=None):
if x.all()==None:
y = np.array([[123], [123]])
else:
y = x
return y
Would return (as expected):
print(test())
[[123]
[123]]
However, with the revised script, if I want x to be none again:
print(test())
Gives a new warning:
**'NoneType' object has no attribute 'all'**
How can I solve this? I want the function to work either with x being a pre-defined matrix or not (a default).
You can use default parameter, then if no argument is provided it will be used
def test(x=np.array([[123], [123]])):
return x

OCTAVE: Checking existence of an element of a cell array

I am using Octave 4.0.0.
I define A{1, 1} = 'qwe', but when I check existence of A{1, 1}, as in
exist("A{1,1}")
or
exist("A{1,1}", "var")
it returns 0.
How can I check its existence?
To check if an array has element say 3, 5, you need to verify that the array has at least 3 rows and 5 columns:
all(size(A) >= [3, 5])
You can of course check if variable A exists at all before-hand, and also is a cell array. A complete solution might be something like
function b = is_element(name, varargin)
b = false;
if ~evalin(['exists("' name '")'], 'caller')
return;
end
if ~strcmp(evalin(['class(' name ')'], 'caller'), 'cell')
return;
end
if evalin(['ndim(' name ')'], 'caller') ~= nargin - 1
return;
end
b = all(evalin(['size(' name ')'], 'caller') >= cell2mat(varargin))
endfunction
This function accepts a variable name and the multi-dimensional index you are interested in. It returns 1 if the object exists as a cell array of sufficient dimensionality and size to contain the requested element.

Tensorflow: tf.reduce_logsumexp returning negative values

I am new to tensorflow framework. I am using
tf.reduce_logsumexp in my code. But inspecting the output I see that some of the values are negative. How is that possible? I suspected that it might be due to some nans or inf values so I put in a check to remove those values in my input like this(X is my input):
res = tf.where(tf.is_inf(X), tf.zeros_like(X), X)
res = tf.where(tf.is_nan(res), tf.zeros_like(res), res)
output = tf.reduce_logsumexp(res, axis=0)
But even this does not help and I still get some values as negative. Any help appreciated! Thanks
Note that the logarithm is negative, if its argument is smaller than 1. Therefore, you will always get a negative logsumexp output if the sum of the exponentials is smaller than 1. This occurs for example if all of the exponents are much smaller than zero, i.e. you have
res = [-2.5, -1.4, -3.3, -1.65, -2.15], then the corresponding exponentials are
exp(res) = [0.082, 0.247, 0.037, 0.192, 0.116], and their sum
sum(exp(res)) = 0.674 smaller than 1.
If you then take the logarithm, you get
log(sum(exp(res))) = log(0.674) = -0.394.
It simply emerges from the definition of the function that it does not necessarily have a positive output. You can test it with the following program:
import numpy as np
def logsumexp(arr):
summ = 0.0
for i in range(arr.shape[0]):
print(np.exp(arr[i]))
summ += np.exp(arr[i])
print('Sum: {}'.format(summ))
return np.log(np.sum(np.exp(arr)))
arr = np.asarray([-2.5, -1.4, -3.3, -1.65, -2.15])
print('LogSumExp: {}'.format(logsumexp(arr)))

Using mapply in a function to detect outliers more than 3sd from the mean returns incorrect values

I wrote a function that is supposed to return for each variable in a dataset a list of values that are more than 3sd apart from their column-mean. Therefore, I used mapply to compare for each single value in the dataset, whether its absolute value is more than three times larger than the sd of the respective variable it belongs to. The function works, however, it gives me a bunch of "outliers" that are not outside of this cutoff. Where might I have gone wrong?
findOutlier <- function(data, cutoff = 3) {
## Calculate the sd
sds <- apply(data, 2, sd, na.rm = TRUE)
## Identify the cells with value greater than cutoff * sd
result <- mapply(function(d, s) {
which(abs(d) > cutoff * s)
}, data, sds)
result
}

Vectorization of cell-array element manipulation

I have a 1xN dimensional cell-array containing matrices of dimension AxB, where A > 0 and B > 2. I want to extract the second and third column of each matrix and create a new cell-array containing these new matrices.
I know I can do this:
newcell = cell(size(oldcell));
for i = 1:size(oldcell,2)
newcell{i} = oldcell{i}(:, [2, 3]);
endfor
But I'm wondering if the loop can be avoided by further vectorization?
I figured it out. This can be done with cellfun(), with the option UniformOutput set to false (the default is true).
newcell = cellfun(#(x) x(:, [2, 3]), oldcell, 'UniformOutput', false);
The reason this doesn't work with UniformOutput=true is that cellfun() then expects the outputs to be scalar, which they are not in this case.