I'm using Matlab to create a GUI. Herefore I'm using the guide function of matlab.
I want to store the slider values in a vector. I am doing this in the callback function:
for i = 1:10
X(i) = get(handles.slider1,'Value');
end
But this results in a vector that stores the same value 10 times. What I actually want is to store the last 10 values of the slider in a vector. Any ideas?
I would suggest to create a 1 x 10 vector of zeros when starting the GUI, i.e. in the OpeningFcn of the GUI:
handles.X = zeros(1,10);
guidata(hObject,handles); % Update handles variable
Then in the Callback function of the slider, you always shift the vector one to the right and add the new value in the first place:
x = get(handles.slider1,'Value');
handles.X = [x, handles.X(1:end-1)];
guidata(hObject,handles); % Update handles variable
Now X always contains the last 10 values of the slider value, X(1) is the last value and so on.
Before the slider hasn't been moved 10 times, some of the values will not be correct, i.e. they will just be zero. If this is a problem, you could grow the X vector dynamically in the Callback.
Related
I'm using this simple code to learn arrays in pine v5:
var float[] my_arr = array.new_float(0)
if barstate.islast
array.push(my_arr, close[1])
a = array.get (my_arr, 0)
plot(a)
I'm trying to insert the previous close in my_arr and plot its value. I think the value of the close[1] should be entered in the array at the index 0 using: array.push() But when I plot that value, It appears to me this message:
The barstate last call will not run until the last bar of the chart. When you load a script it runs on all historical bars first beginning at the first bar in time. The array.get call is trying to pull a value from an array that is not populated. You can put in a ternary check to make sure the array size is greater than 0, or you could initialize your array with a size and a value like (1) which would give the first populated value na until populated by your of statement. If you just want to plot close[1] you can skip the array and just plot that series
Cheers
I have 3 graphs of an IV curve (monotonic increasing function. consider a positive quadratic function in the 1st quadrant. Photo attached.) at 3 different temperatures that are not obtained linearly. That is, one is obtained at 25C, one at 125C and one at 150C.
What I want to make is an interpolated 2D array to fill in the other temperatures. My current method to build a meshgrid-type array is as follows:
H = 5;
W = 6;
[Wmat,Hmat] = meshgrid(1:W,1:H);
X = [1:W; 1:W];
Y = [ones(1,W); H*ones(1,W)];
Z = [vecsatIE25; vecsatIE125];
img = griddata(X,Y,Z,Wmat,Hmat,'linear')
This works to build a 6x6 array, which I can then index one row from, then interpolate from that 1D array.
This is really not what I want to do.
For example, the rows are # temps = 25C, 50C, 75C, 100C, 125C and 150C. So I must select a temperature of, say, 50C when my temperature is actually 57.5C. Then I can interpolate my I to get my V output. So again for example, my I is 113.2A, and I can actually interpolate a value and get a V for 113.2A.
When I take the attached photo and digitize the plot information, I get an array of points. So my goal is to input any Temperature and any current to get a voltage by interpolation. The type of interpolation is not as important, so long as it produces reasonable values - I do not want nearest neighbor interpolation, linear or something similar is preferred. If it is an option, I will try different kinds of interpolation later (cubic, linear).
I am not sure how I can accomplish this, ideally. The meshgrid array does not need to exist. I simply need the 1 value.
Thank you.
If I understand the question properly, I think what you're looking for is interp2:
Vq = interp2(X,Y,V,Xq,Yq) where Vq is the V you want, Xq and Yq are the temperature and current, and X, Y, and V are the input arrays for temperature, current, and voltage.
As an option, you can change method between 'linear', 'nearest', 'cubic', 'makima', and 'spline'
I was wondering what a function would look like in order to change values in an array according to its location. In the script I have attached, I use a function I wrote to generate an array for voltage and current and plot these values in order to give me my IV curve. The inputdlg feature however is not in use. I would like to use the inputdlg box to re run the function for calculating I and V, then I would replace values in the first array with these new values and plot the changes. What I want to know is how to perform some function upon clicking OK on the dialog box and replacing values in an existing array with the output values from the function at a location specified by the user.
Here is where I start: all of these inputs are from edit boxes in the GUI
function plot_button_Callback(hObject, eventdata, handles)
% hObject handle to plot_button
% Get user input from GUI
NumS = str2double(get(handles.NumSeries_input,'String'));
%number of cells in series
NumP = str2double(get(handles.NumParallel_input,'String'));
%number of cells in parallel
Rs = eval(get(handles.Rseries_input,'String'));%Series resistance (Ohm)
Rsh = eval(get(handles.Rshunt_input,'String')); %Shunt resistance (Ohm)
Isc = eval(get(handles.Isc_input,'String')); %Short circuit current (A)
Voc = eval(get(handles.Voc_input,'String')); %Open circuit voltage (V)
n = eval(get(handles.n_input,'String')); %Ideality factor
% Calculate data
Here I open up a dialog box in order to set the params for the new cell
headers ={'Param1' 'Param2' 'Param3' 'Param4' 'Param5' 'Location'};
dlg_title = 'Input';
num_lines = 1;
def = round(rand(1,6)*20);
def = def';
def = num2str(def);
deff = cellstr(def);
answer = inputdlg(headers, dlg_title, num_lines, deff);
%Constants
%Parameters
CalculationIVRsRsh is defined else where in my code
T=-140; %Temperature in degree C
%Constantes
q=1.602176565e-19; %Charge elementaire (C)
k=1.3806488e-23; %Boltzmann constant (J/K)
%Size of the cell
[garb, taille]=size(Isc);
%Calculation of each cell characteristics
for ind=1:taille
[I(:,ind), V(:,ind)]=CalculationIVRsRsh(Isc(ind),Voc(ind),T,n(ind),Rs(ind),Rsh(ind));
end
Here I replicate the Current (I) array according to how many cells are in parallel
%Combination of the 3 solar cells
Isc3=min(Isc);
IscTm=repmat(Isc',1,NumP); %replicates the input vector for the Isc
%according to how many of the cells in the array are in parallel
IscT=sum(IscTm,2); %sums the Isc for the array
Isc4=min(IscT); %takes the current limitting value
Iint=-Isc3/20:0.01:min(Isc3);
IintP1=repmat(Iint,NumP,1); %replicates the values for Iint for the IV curve
IintP=sum(IintP1,1); %adds the IintP1 values to simulate the adding currents
for ind=1:taille
Vint(:,ind)=interp1(I(:,ind),V(:,ind),Iint);
IscN(ind)=interp1(V(:,ind),I(:,ind),0);
end
%We are doing the sum of V starting from the lowest I, therefore the 2
%other cells are already at a positive voltage for which the sum is the
%minimum value we can obtain for the 3 junction cell
Here I replicate the voltage array according to how many cells are in series
Isc3=min(IscN);
V3=sum(Vint,2);
Vs=repmat(V3,1,NumS);
V4=sum(Vs,2);
Voc3=sum(Voc);
VocT=NumS.*Voc3;
Then I plot new data
%plots data
V3=cat(1,V3,0);
I3=cat(1,Iint',Isc3);
I4=cat(1,IintP',Isc4);
V4=cat(1,V4,0);
plot(V3,I3,V4,I4)
axis([0 VocT+VocT/20 0 max(IscT)+max(IscT)/20]);
xlabel('V (V)');
ylabel('I (A)');
legend('Cell', 'Array');
I'm trying to do an homemade version of peakfinder.m, by making it work with multiple arrays instead of just one at a time, for more time efficient performance. (http://www.mathworks.com/matlabcentral/fileexchange/25500-peakfinder)
I have a 2D matrix where I need to find if the sign changes in the 2nd dimension.
dx0 = diff(x0,1,2); % Find derivative
dx0(dx0 == 0) = -eps; % This is so we find the first of repeated values
ind = find(dx0(:,1:end-1).*(dx0(:,2:end)) < 0)+1; % Find where the derivative changes sign
Now my problem is that it does find where the derivative changes sign, but it is one big vector. So if the signs changes twice in the same row (or doesn't in a row), I have no way to find out.
So if x0 is of size 1000x10, I'd like ind to be of size 1000xY, where Y is the number of times it changes sign in EACH row. I also need to know at which values of x0 there is a sign change. So each row will be in the style of :
2 4 7
4 8
2 5 6 8
etc.
Is this possible at all? Or should I change the code so it places a 0 if it doesn't change and a 1 if it does change, considering I'll be working with the values where it changes?
cellfun approach -
b1 = padarray(sign(dx0(:,1:end-1))~=sign(dx0(:,2:end)),[0 1],'pre')
out = cellfun(#find,mat2cell(b1,ones(1,size(b1,1)),size(b1,2)),'uni',0)
The above code assumes you have padarray which seems like a recent addition to MATLAB's Image Processing Toolbox. So, if you don't have it, you can concatenate zeros (with false) like this -
b1 = sign(dx0(:,1:end-1))~=sign(dx0(:,2:end))
b1 = [false(size(b1,1),1) b1]
out = cellfun(#find,mat2cell(b1,ones(1,size(b1,1)),size(b1,2)),'uni',0)
Alternative solution using cellfun with nonzeros function -
b1 = padarray(sign(dx0(:,1:end-1))~=sign(dx0(:,2:end)),[0 1],'pre')
out = cellfun(#nonzeros,mat2cell(bsxfun(#times,b1,1:size(b1,2)),ones(1,size(b1,1)),size(b1,2)),'uni',0)
out contains the locations of sign change across the rows, which can be displayed using celldisp(out).
The counts of the sign changes can be calculated using -
counts = cellfun(#numel,out)
I'm a beginner Lua user, I attempt to create something in Lua by using Love2D libraries.
In the loading function I create a table and upload it with elements (which are numbers) for use it later as a multidimensional array.
function love.load()
Maximum_X = 32
Maximum_Y = 16
Start_X = 64
Start_Y = 32
MapTable = {} -- empty table
for i=1,Maximum_X*Maximum_Y do -- uploading table
table.insert(MapTable, 2)
end
end
Then I make a function that takes changes in the table. Because I'm just experimenting with tables, there's only one changed value. At least, I thought.
function KatamoriGen()
MapTable[4] = 3
end
function love.update(dt)
KatamoriGen()
end
After that, I print the elements of the table in a matrix with 32 coloumns and 16 rows. I see here that not only the 4th element of 1st row is changed, but also the 2nd element of 2nd row and 1st element of 4th row becomes 3.
It obviously means that Table[posX*posY] doesn't work neither since the result of the multiplication is a number like 4 and the operation would change every elements where
X coordinate + Y coordinate = posX*posY
is true. In the example code, the right side of this equation was 4.
A small question: why is it happening?
The main question is: how can I identify elements of MapTable exactly? How can I implement X and Y dimensions to Lua tables? to use them as two-dimensional arrays? Maybe table of tables?
EDIT: this is the drawing function:
function love.draw()
for j=1,16 do
for i=1,32 do
love.graphics.draw(Tileset[MapTable[j*Maximum_X + i]], Start_X + 32*(i-1), Start_Y + 32*(j-1))
end
end
end
Now it's clear for me that this is wrong and the right rule is MapTable[j*Maximum_X + i] but I get an error for it: "expected parameter type: expected userdata"
You can also use multi-dim tables. Something like:
local MapTable = {}
local Maximum_X, Maximum_Y = 32, 16
local Start_X, Start_Y = 64, 32
function love.load()
for y = 1,Maximum_Y do
local row = {}
for x = 1,Maximum_X do
table.insert(row,2)
end
table.insert(MapTable,row)
end
end
function love.draw()
for y,row in ipairs(MapTable) do
for x,idx in ipairs(row) do
love.graphics.draw(Tileset[idx], Start_X + 32*(x-1), Start_Y + 32*(y-1))
end
end
end
As Alex shows it, the problem was not with the way how table works, but rather that I displayed the numbers on a wrong way. Tables can be used as one-dimensional arrays, and everything fine then.
Even though it's not a solution for using them as 2-dimensional array, the main problem is solved.