|  |  |  |    <library code="--[[ Helper function to create a series from arrays

 new_series: a series previously created with ScatterXY.new(name)
 prefix:     prefix of the timeseries, before the index of the array
 suffix_X:   suffix to complete the name of the series containing the X value. If [nil], use the index of the array.
 suffix_Y:   suffix to complete the name of the series containing the Y value
 timestamp:   usually the tracker_time variable
              
 Example:
 
 Assuming we have multiple series in the form:
 
   /trajectory/node.{X}/position/x
   /trajectory/node.{X}/position/y
   
 where {N} is the index of the array (integer). We can create a reactive series from the array with:
 
   new_series = ScatterXY.new("my_trajectory") 
   CreateSeriesFromArray( new_series, "/trajectory/node", "position/x", "position/y", tracker_time );
--]]

function CreateSeriesFromArray( new_series, prefix, suffix_X, suffix_Y, timestamp )
  
  --- clear previous values
  new_series:clear()
  
  --- Append points to new_series
  index = 0
  while(true) do

    x = index;
    -- if not nil, get the X coordinate from a series
    if suffix_X ~= nil then 
      series_x = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_X) )
      if series_x == nil then break end
      x = series_x:atTime(timestamp)	 
    end
    
    series_y = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_Y) )
    if series_y == nil then break end 
    y = series_y:atTime(timestamp)
    
    new_series:push_back(x,y)
    index = index+1
  end
end

--[[ Similar to the built-in function GetSeriesNames(), but select only the names with a give prefix. --]]

function GetSeriesNamesByPrefix(prefix)
  -- GetSeriesNames(9 is a built-in function
  all_names = GetSeriesNames()
  filtered_names = {}
  for i, name in ipairs(all_names)  do
    -- check the prefix
    if name:find(prefix, 1, #prefix) then
      table.insert(filtered_names, name);
    end
  end
  return filtered_names
end

--[[ Modify an existing series, applying offsets to all their X and Y values

 series: an existing timeseries, obtained with TimeseriesView.find(name)
 delta_x: offset to apply to each x value
 delta_y: offset to apply to each y value 
  
--]]

function ApplyOffsetInPlace(series, delta_x, delta_y)
  -- use C++ indeces, not Lua indeces
  for index=0, series:size()-1 do
    x,y = series:at(index)
    series:set(index, x + delta_x, y + delta_y)
  end
end
"/> |  |  |  |  |