function transposeToTimeslices(metricInstances) {
  if (!metricInstances || metricInstances.length === 0) return metricInstances

  const timestamps = metricInstances[0].data.map(tsv => tsv.ts)
  return timestamps.map(ts => {
    const values = getAllMetricInstancesAtTs(metricInstances, ts)
    // transform to a hierarchy of associative objects rather than an array of tuples
    const transformed = values.reduce((acc, { metric, instance, value }) => {
      acc[metric] = acc[metric] || {}
      acc[metric][instance] = value
      return acc
    }, {})
    return { ts, values: transformed }
  })
}
Note: this only keeps timestamps which are present in the first index