TV has not function to detect dominant CycleLength. Script has some problems and I cannot find them - pine-script-v5

The code has an array or loop error or cannot use the information. I want to calculate for 1 to 100 all cycles. And from these Cycles it should find out the most dominant cycle length and plot this dominant one to the chart. Better would be to get the 3 most dominant cycles and put them together into one plotted line. Please help! unfortunately
TV has no functions for detecting dominant cycles and this should solve the problem but it hast some script Problems.
//#version=5
// Import the ta-lib library
indicator("ta-lib")
// Define the period range for the analysis
periodStart = 1
periodEnd = 100
// Define the data series
dataSeries = close
// Create an array to store the magnitude of the DFT for each period
magnitudeArray = array.new<float>(periodEnd)
// Loop over the periods
for period = periodStart to periodEnd
// Initialize the real and imaginary parts of the DFT for each period
re = 0.0
im = 0.0
// Loop over the data for each period
for i = 0 to period-1
re := re + dataSeries[i]*math.cos(-2*math.pi*i/period)
im := im + dataSeries[i]*math.sin(-2*math.pi*i/period)
// Calculate the magnitude of the complex numbers for each period
magnitudeArray[period] := math.sqrt(re*re + im*im)
// Initialize a variable to store the maximum magnitude and its corresponding period
maxMagnitude = 0.0
dominantCyclePeriod = 0
// Loop over the magnitude array to find the period with the highest magnitude
for period = periodStart to periodEnd
if array.max(magnitudeArray[period]) > maxMagnitude
maxMagnitude = array.max(magnitudeArray[period])
dominantCyclePeriod = period
// Plot the dominant cycle period on the chart
plot(dominantCyclePeriod)

Related

How to increase time by 1s and replace old DT_i with the new one

I'm trying to calculate the DT value from a model I set up on Sim4Life. Firstly, i'd like to say that I am a complete beginner and I am trying to understand how programming works in general.
Now, I have a function with some constants and two variables, the one being time Dt (starting from 1 sec to 900 secs) and the other being the initial DT_i value. I want to calculate the increase of temperature for every second and create a loop that replaces the DT_i value with the DT_1_i value and also calculates the increased temperature DT_i_1. The function looks like this: DT_1_i=DT_i+Dt.
I know it is a very simple problem but I couldn't work my way through other similar questions. Any help would be appreciated.
Temperature variation:
You need initial temperature variation , I used 0
T(i+1) stands for Next temperature variation
T(i) stands for present temperature variation
i stands for time step, dt
Read through comment in my code
Time
Use for loop to set the time for i = 1 : 900 %Temperature increase end
i =1:900 just means
first run use time = 1s,
second run time = 1+1 = 2
so on till 900
The code is as follow
% Initial Temperature variation is set to zero, unless you have some data
d = 1.3;
c = 3.7;
S_i = 3*10^3;
t_reg = 900;
%Time
t = 1:900;
% Length oftime to help me know the size of the variable needed to
% initialize
l = length(t);
% Initialize variable that used to store DT it helps speed up
% comutation
% Initial Temperature variation is set to zero, unless you have some data
DT = zeros(1, l);
for i = 1:900
% the value of i represent dt, first run i = 1, dt = 1, second run
% i = 2 and dt = 2 so on
if i == 900
%do nothing already reached the last index 900, i+1 = 901 will be
%out of range
else
DT(i+1) = DT(i) + (i./t_reg).*(d.*sqrt(c*S_i)-DT(i+1));
end
end

What's wrong with my code in Matlab?

I want to play all frequencies given in matrix(FrTm) with its duration.The actual duration is one second but each frequency has to play for 3 of 1/18 and 6 of 1/18 seocnd such as given in matrix(FrTm).
function Music()
Fs=44100;
T=1/Fs;
M = zeros(1,88);
for I=7:88,
M(I) = round(36.8*(2^(1/12))^(I-6));
end
Signal=[];
FrTm=[50,3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
t=0:1/18:1;
for i=1:length(FrTm),
M(i)=FrTm(i);
Z=M(i);
data= sin(2*pi*Z/Fs*t);
signal=[data;signal];
end
stem(Signal);
sound (Signal, 44100);
end
The classical way to make a sound with a given frequency (f) and sample frequency (Fs) is to make a time vector with step 1/Fs:
time = 0:1/Fs:D;
Where Dis the duration of the signal. The signal itself is then:
signal = sin(2*pi*f.*time)
In this case the total time is fixed, not the time of each signal. The total time is denoted with T, and the total time vector is made as
time = 0:1/Fs:T;
The sum of the second column is the total number of units the vector time needs to be divided in, e.g. 50, 3 means that a signal at 50 Hz needs to be played for 3 units. This means we only need a time vector of the length of 3 units:
t = time(1:floor(end*duration/s));
Where duration is the number of units for this part and s is the total number of units. The signal is then simply, as stated above,
data = sin(2*pi*f*t);
The data is then appended to the whole signal. The complete code, looks like this:
Fs = 44100; % sample frequency [Hz]
T = 3; % total duration [s]
time = 0:1/Fs:T;
% matrix with frequencies and duration
FrTm=[50,3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
s = sum(FrTm(:,2));
[m, ~] = size(FrTm);
signal = [];
for i=1:m
freq = FrTm(i,1);
duration = FrTm(i,2);
t = time(1:floor(end*duration/s));
data = 10*sin(2*pi*freq.*t);
signal = [data signal];
end
stem(signal);
sound(signal, 44100);
Note instead of declaring time in the beginning, it is possible to make a new vector each time you run through the loop. In that case omit time = 0:1/Fs:T; and change t = time(1:floor(end*duration/s)); to t = 0:1/Fs:floor(end*duration/s);
function Music()
Fs=44100;
T=1/Fs;
M = zeros(1,88);
for I=7:88,
M(I) = round(36.8*(2^(1/12))^(I-6));
end
Signal=[];
FrTm=[50 3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
for i=1:length(FrTm),
%---------------------------------------------------
% complete the function
freq = FrTm(i,1);
duration = FrTm(i,2);
time =0:1/Fs:1; % change the 1 to change total duration
s = sum(FrTm(:,2));
t = time(1:floor(end*duration/s));
data = sin(2*pi*freq.*t);
Signal = [data Signal];
end
stem(Signal);
sound (Signal, 44100);
end
This is the exact code what i wanted ViG can you please remove this tak tak sound it just a noise actually how to use envelope function to remove thid tak tak sound in music code is following.
Fs=44100;
T=1/Fs;
M=zeros(1,88);
for I=7:88
M(I)=round(36.8*(2^(1/12))^(I-6));
end
signal=[];
FrTm=[50,3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
for i=1:length(FrTm)
x=FrTm(i,1);
y=FrTm(i,2);
F=M(x);
time=0:1/Fs:y/18;
sinewave=sin(2*pi*F*time);
signal=[signal sinewave];
end
stem(signal)
sound(signal,Fs)

Count time intervals for events greater than threshold

I am stuck at something in MATLAB and would appreciate if someone can help. Here is what I would like to do. I have a velocity field data w.r.t. time (see figure attached).
I would like to count number of time intervals (T1,T2,T3,etc) for which value of velocity is greater than threshold. Please note that I would like to count time intervals and not number of velocity points above threshold.
After doing step 1, I would like to somehow calculate average of time duration (e.g. average of T1, T2, T3, etc).
Finally, I want to calculate average value of velocity data for intervals T1, T2, T3, etc.
I think step 2 and 3 should be straightforward if I can get step 1 done. I would really appreciate any help. I am doing this in MATLAB but I am open to use any other tools if required.
I'd suggest the use of bwconncomp:
A = rand(1,100); %your 1d list of speeds
T = 0.5;
B = A > T;
tmp = bwconncomp(B);
pxlist = tmp.PixelIdxList; %connected components are above thresh
N = zeros(1,length(pxlist));
V = zeros(1,length(pxlist));
for li = 1:length(pxlist)
N(li) = length(pxlist{li});
V(li) = mean(A(pxlist{li})); %avg velocity in interval li
end
avg = mean(N); %this is the avg. "time", i.e. length of connected components

matlab - averaging for a given interval

I can calculate daily averages of a data set like so:
Jday = datenum('2010-11-01 00:00','yyyy-mm-dd HH:MM'):60/(60*24):...
datenum('2011-02-31 23:00','yyyy-mm-dd HH:MM');
Dat = rand(length(Jday),1);
DateV = datevec(Jday);
[~,~,b] = unique(DateV(:,1:3),'rows');
AvDat = abs(accumarray(b,Dat,[],#nanmean));
AvJday = abs(accumarray(b,Jday,[],#nanmean));
However, I would like to take an average of a data set given a number for the output resolution. For example, if I wrote
outRes = 86400; % in seconds
I would like to average the values so that the output resolution is equal to 86400 seconds, and if the outRes defined is shorter than the resolution of the data then no averaging will take place.
How can this be done?
You should be able to detect the resolution of the data by:
CurrentRes=mean(diff(Jday))*86400;
if (~all(diff(Jday)==CurrentRes))
error('Inequally distributed sampling times');
end
if (CurrentRes>outRes)
return;
Then the amount you need to downsample by is:
AveragingFactor=outRes/CurrentRes;
Then you can average by discarding some samples at the end (or start) and averaging:
Dat = reshape(Dat(1:end-mod(length(Dat),AveragingFactor),:),AveragingFactor,[]);
AvDat = mean(Dat,1)'; % Transpose to keep it as a column vector if necessary.

Finding the difference between two signals

I have two signals, let's call them 'a' and 'b'. They are both nearly identical signals (recorded from the same input and contain the same information) however, because I recorded them at two different 'b' is time shifted by an unknown amount. Obviously, there is random noise in each.
Currently, I am using cross correlation to compute the time shift, however, I am still getting improper results.
Here is the code I am using to calculate the time shift:
function [ diff ] = FindDiff( signal1, signal2 )
%FINDDIFF Finds the difference between two signals of equal frequency
%after an appropritate time shift is applied
% Calculates the time shift between two signals of equal frequency
% using cross correlation, shifts the second signal and subtracts the
% shifted signal from the first signal. This difference is returned.
length = size(signal1);
if (length ~= size(signal2))
error('Vectors must be equal size');
end
t = 1:length;
tx = (-length+1):length;
x = xcorr(signal1,signal2);
[mx,ix] = max(x);
lag = abs(tx(ix));
shifted_signal2 = timeshift(signal2,lag);
diff = signal1 - shifted_signal2;
end
function [ shifted ] = timeshift( input_signal, shift_amount )
input_size = size(input_signal);
shifted = (1:input_size)';
for i = 1:input_size
if i <= shift_amount
shifted(i) = 0;
else
shifted(i) = input_signal(i-shift_amount);
end
end
end
plot(FindDiff(a,b));
However the result from the function is a period wave, rather than random noise, so the lag must still be off. I would post an image of the plot, but imgur is currently not cooperating.
Is there a more accurate way to calculate lag other than cross correlation, or is there a way to improve the results from cross correlation?
Cross-correlation is usually the simplest way to determine the time lag between two signals. The position of peak value indicates the time offset at which the two signals are the most similar.
%// Normalize signals to zero mean and unit variance
s1 = (signal1 - mean(signal1)) / std(signal1);
s2 = (signal2 - mean(signal2)) / std(signal2);
%// Compute time lag between signals
c = xcorr(s1, s2); %// Cross correlation
lag = mod(find(c == max(c)), length(s2)) %// Find the position of the peak
Note that the two signals have to be normalized first to the same energy level, so that the results are not biased.
By the way, don't use diff as a name for a variable. There's already a built-in function in MATLAB with the same name.
Now there are two functions in Matlab:
one called finddelay
and another called alignsignals that can do what you want, I believe.
corr finds a dot product between vectors (v1, v2). If it works bad with your signal, I'd try to minimize a sum of squares of differences (i.e. abs(v1 - v2)).
signal = sin(1:100);
signal1 = [zeros(1, 10) signal];
signal2 = [signal zeros(1, 10)];
for i = 1:length(signal1)
signal1shifted = [signal1 zeros(1, i)];
signal2shifted = [zeros(1, i) signal2];
d2(i) = sum((signal1shifted - signal2shifted).^2);
end
[fval lag2] = min(d2);
lag2
It is computationally worse than cross-calculation which can be speeded up by using FFT. As far as I know you can't do this with euclidean distance.
UPD. Deleted wrong idea about cross-correlation with periodic signals
You can try matched filtering in frequency domain
function [corr_output] = pc_corr_processor (target_signal, ref_signal)
L = length(ref_signal);
N = length(target_signal);
matched_filter = flipud(ref_signal')';
matched_filter_Res = fft(matched_filter,N);
corr_fft = matched_filter_Res.*fft(target_signal);
corr_out = abs(ifft(corr_fft));
The peak of the matched filter maximum-index of corr_out above should give you the lag amount.