how to plot the difference of two Timelion time series alongside them - kibana

I have two long time series in timelion with different labels like example1 and example2:
.es(q='(supported_version : true) && NOT (token : Alerter) && (upstream: example )').mvavg(window=1h).divide(.es(q='(supported_version : true) && NOT (token : Alerter) && NOT (_exists_:(enriched)) && upstream: example').mvavg(window=1h)).label('example1').yaxis(units='percent',tickDecimals=2).precision(5).lines(show=true,fill=0.5, width=2)
I want to plot both of them plus their difference.
currently to achieve the difference bar I copy and paste both of them as follows:
(...first time series...).subtract(...second time series...)
but It's two long and messy.
how can I plot the difference without copy and pasting them? (e.g. using their labels or by assigning them to two variables if it's possible)

Related

Accessing API with for-loop randomly has encoding error, which breaks loop in R

I'm trying to access an API from iNaturalist to download some citizen science data. I'm using the package rinat to get this done (see vignette). The loop below is, essentially, pulling all observations for one species, in one state, in one year iteratively on a per-month basis, then summing the number of observations for that year (input parameters subset from my actual script for convenience).
require(rinat)
state_ids <- c(18, 14)
bird_ids <- c(14886,1409)
months <- c(1:12)
final_nums <- vector()
for(i in 1:length(state_ids)){
total_count <- vector()
for(j in 1:length(months)){
monthly <- get_inat_obs(place_id=state_ids[i],
taxon_id=bird_ids[i],
year=2019,
month = months[j])
total_count <- append(total, length(monthly$scientific_name))
print(paste("done with month", months[j], "in state", state_ids[i]))
}
final_nums <- append(final_nums, sum(total_count))
print(paste("done with state", state_ids[i]))
}
Occasionally, and seemingly randomly, I get the following error:
No encoding supplied: defaulting to UTF-8.
Error in if (!x$headers$`content-type` == "text/csv; charset=utf-8") { :
argument is of length zero
This ends up breaking the loop or makes the loop run without actually pulling any real data. Is this an issue with my script, or the API, or something else? I've tried manually supplying encoding information to the get_inat_obs() function, but it doesn't accept that as an argument. Thank you in advance!
I don't believe this is an error in your script. The issue is with the api most likely.
the error argument is of length zero is a common error when you try to make a comparison that has no length. For example:
if(logical(0) == "TEST") print("WORKED!!")
#Error in if (logical(0) == "TEST") print("WORKED!!") :
# argument is of length zero
I did some a few greps on their source code to see where this if statement is and it seems to be within inat_handle line 211 in get_inate_obs.R
This would suggest that the authors did not expect for
!x$headers$`content-type` == 'text/csv; charset=utf-8'
to evaluate to logical(0), but more specifically
x$headers$`content-type`
to be NULL.
I would suggest making a bug report on their GitHub and recommend they change the specified line to:
if(is.null(x$headers$`content-type`) || !x$headers$`content-type` == 'text/csv; charset=utf-8'){
Suggesting a bug is usually more well received if you have a reproducible example.
Also, you could totally make this change yourself locally by cloning out the git repository, editing the file, rebuild the package, and then confirm if you no longer get an error in your code.

Pine Script: How to display current time in chart's timezone on label, at every price update?

I am attempting to do something seemingly trivial, but running into all sorts of problems.
I would like to plot certain basic information on a label every time there is an update to the current price--regardless of the timeframe of my chart.
I am able to accurately display volume and price information, however displaying the time has been a challenge.
My first attempt was to use the following code:
if (barstate.islast)
label.set_text(
id=myLabel,
text="\nTime: " + tostring(hour) + ":" + tostring(minute) + ":" + tostring(minute)
)
I quickly learned that, even though my chart is set to the timezone for New York (i.e., UTC-4), calling tostring(hour) displays the hour of UTC.
Figuring out how to specify that I want it displayed time to correspond to my chart's timezone has been the first major hurdle, and I have tangled endlessly with timestamp() and syminfo.timezone to no avail.
My second major problem is that tostring(second) does not properly display the seconds, even for UTC time.
While working on a 1m chart, I thought I managed to solve this by implementing
tostring((timenow-time)/1000)
However, the seconds do not display properly on different time frames.
This is all in addition to the fact that charts from different exchanges in different time zones will all display time "incorrectly" with respect to UTC time.
It must to be the case that I am missing something fairly basic, since time is such crucial data, but I just can't determine the proper syntax.
Thanks in advance for any assistance.
A few different issues are at play here:
Pine scripts have no visibility on the chart's timezone you may have selected manually. That only affects the display of the chart.
The minute variable returns the minute at the beginning of the bar, so will not change on script iterations in the realtime bar, until a new bar begins. To get the current minute you will need to use an overloaded version of minute where you can specify a timestamp in ms. The timenow built-in variable returns the timestamp for the time of a particular script iteration (that is true in the realtime bar; when the script is running on historical bars, timenow is only updated every second during the script's execution). So you need to use minute(timenow).
If you want minute() to return a time in another timezone than the exchange's, you can use a second parameter to specify a timezone, which is what we do in the second example here. In our example you can change the timezone through the script's "Settings/Inputs". Used with the timezone, minute() will look something like:
minute(timenow, "GMT-4").
//#version=4
study("", "Time", true)
i_timeZone = input("GMT-4")
f_print(_txt) => var _lbl = label.new(bar_index, highest(10)[1], _txt, xloc.bar_index, yloc.price, #00000000, label.style_none, color.gray, size.large, text.align_left), label.set_xy(_lbl, bar_index, highest(10)[1]), label.set_text(_lbl, _txt)
f_print(tostring(hour(timenow), "00:") + tostring(minute(timenow), "00:") + tostring(second(timenow), "00") + " (Exchange)\n")
f_print(tostring(hour(timenow, i_timeZone), "00:") + tostring(minute(timenow, i_timeZone), "00:") + tostring(second(timenow, i_timeZone), "00") + " (Input: " + i_timeZone + ")")

How do I create a loop function to apply acoustic indices from "soundecology" to specific sections of .wav files using R

I have a large quantity of .wav files that I need to analyze using the acoustic indices from the "soundecology" package in R. However, the recordings do not have uniform start times and I need to analyze specific periods of time within the files. I want to create a function and loop for automating the process.
I have created a spread sheet for each folder of recordings (each folder is a different location) that lays out the recording and the times within each recording that I need to analyze. Basically, a row contains: the sound file name, the time when the sample should start (eg. 09:00:00, the number of seconds from the start of the file that that time occurs, and the munber of seconds from the start time of the file that the end of the sample should occur.
That data looks like this:
Spread sheet of data
I am using the package "tuneR" and "warbleR" to select the specific portion of a sound file that I want to analyze. Here is the the code and the output that I would like to loop across all the sound files:
wavrow1 <-read_wave(mvb$sound.files[1], from = mvb$start[1], to = mvb$end[1])
wavrow1.aci <- acoustic_complexity(wavrow1, j=10)
which yeilds
max_freq not set, using value of: 22050
min_freq not set, using value of: 0
This is a mono file.
Calculating index. Please wait...
Acoustic Complexity Index (total): 934.568
However, when I put this into a function in order to then put it into a loop I get a different output.
acianalyzeFUN <- function(mvb, i){
r <- read_wave(mvb$sound.files[i], mvb$start[i], mvb$end[i])
soundfile.aci <- acoustic_complexity(r, j=10)
}
row1.test <- acianalyzeFUN(mvb, 1)
This gives the output:
max_freq not set, using value of: 22050
min_freq not set, using value of: 0
This is a mono file.
Calculating index. Please wait...
Acoustic Complexity Index (total): 19183.03
Acoustic Complexity Index (by minute): 931.98
Which is different.
So I need to fix this function and put it into a loop so that I can apply it across all the files and save the results into a data frame or ultimately another spread sheet.
I was thinking a loop like the following might work but I am also getting errors with it:
output <- vector("logical", length(97))
for (i in seq_along(mvb$sound.files)) {
output[[i]] <- acianalyzeFUN(mvb, i)
}
Which returns this error:
max_freq not set, using value of: 22050
min_freq not set, using value of: 0
This is a mono file.
Calculating index. Please wait...
Acoustic Complexity Index (total): 19183.03
Acoustic Complexity Index (by minute): 931.98
Error in output[[i]] <- acianalyzeFUN(mvb, i) :
more elements supplied than there are to replace
Thanks for any help and advice on this. Please let me know if there are any other pieces of information that would be helpful.
the read_wave function takes following arguments :
read_wave(X, index, from = X$start[index], to = X$end[index], channel = NULL,
header = FALSE, path = NULL)
In the manual test, you specify from = mvb$start[1], to = mvb$end[1]
In the function you created, you dont specify the arguments :
r <- read_wave(mvb$sound.files[i], mvb$start[i], mvb$end[i])
so that mvb$start[i] gets affected to index and mvb$end[i] to from.
You should write:
acianalyzeFUN <- function(mvb, i){
r <- read_wave(mvb$sound.files[i], from = mvb$start[i], to = mvb$end[i])
soundfile.aci <- acoustic_complexity(r, j=10)
}
This should explain the difference you observe.
Regarding the error, you create a vector of logical to collect the result, but acianalyzeFUN returns nothing : it just sets two variables r and soundfileaci without returning anything.

Multiple altair charts generated by the same cell

I have a list of pandas dataframes I named entries, which I want to visualize after running code from the same cell. Below is the code I used :
alt.data_transformers.disable_max_rows()
for entry in entries :
entry['ds'] = entry.index
entry['y'] = entry['count']
entry['floor'] = 0
serie = alt.Chart(entry).mark_line(size=2, opacity=0.7, color = 'Black').encode(
x=alt.X('ds:T', title ='date'),
y='y'
).interactive().properties(
title='Evolution of '+entry.event.iloc[0]+' events over time'
)
alt.layer(serie)\
.properties(width=870, height=450)\
.configure_title(fontSize=20)
When i run the same code out of the 'for' loop, I get to see the one chart that corresponds to one dataframe, but once I run the code above, I don't get any graphs at all.
Does anyone know why It's not working or how to solve this issue?
TLDR: use chart.display()
Unless a chart appears at the end of the cell, you must manually display it.
By analogy, if you run
x + 1
by itself, Python will display the result. However, if you run
for x in range(10):
x + 1
Python will not display anything, because the last statement in the cell (in this case the for loop) has no return value to display. Instead you have to write
for x in range(10):
print(x + 1)
For altair, the mechanism is similar: if the chart is defined in the last statement in the cell, it will be automatically displayed. Otherwise, you have to manually trigger the display, which you can do using the display method:
for i in range(10:
chart = alt.Chart(...)
chart.display()
For more information on display troubleshooting in Altair, see https://altair-viz.github.io/user_guide/troubleshooting.html

Constructing a return in R

I have a function in R that I run on lists of flies. After the following code I apply the function to files and have R put the values in a new file. An equation in this function outputs a value based on water density and depth. I found that the top row of the depth is not always 1 in these files, but I need it to be for the equation. I would like to be able to output an "NA" message into the new sheet for when it is not.
stratindex=function(file){
ctd=read.csv(file,header=T)
x=ctd$Density..sigma.t..kg.m.3..
y=ctd$Depth..salt.water..m...lat...60
if(y[1]!=1){return(NA)} else
((x[30]-x[1]) / 29)
}
This all reads in fine. Then I get to the next part, where it takes the individual files and applies the function to them.
the.files <- choose.files()
index <- sapply(the.files, stratindex)
After this, R prompts:
"Error in if (y[1] != 1) { : missing value where TRUE/FALSE needed"
Where did I go wrong? What can I do to nest other stipulations if I find them? For instance, if the depth at row 30 is not 30.

Resources