/// <summary> /// 3-d OLAP cube operator; Fills all cells of the given vectors into the given histogram. /// If you use Hep.Aida.Ref.Converter.ToString(histo) on the result, the OLAP cube of x-"column" vsd y-"column" vsd z-"column", summing the weights "column" will be printed. /// For example, aggregate sales by product by region by time. /// <p> /// Computes the distinct values of x and y and z, yielding histogram axes that capture one distinct value per bin. /// Then fills the histogram. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="weights"></param> /// <returns>the histogram containing the cube.</returns> /// <excption cref="ArgumentException">if <i>x.Count != y.Count || x.Count != z.Count || x.Count != weights.Count</i>.</excption> public static Hep.Aida.IHistogram3D cube(DoubleMatrix1D x, DoubleMatrix1D y, DoubleMatrix1D z, DoubleMatrix1D weights) { if (x.Size != y.Size || x.Size != z.Size || x.Size != weights.Size) { throw new ArgumentException("vectors must have same size"); } var epsilon = 1.0E-9; var distinct = new DoubleArrayList(); var vals = new double[x.Size]; var sorted = new DoubleArrayList(vals); // compute distinct values of x vals = x.ToArray(); // copy x into vals sorted.Sort(); Cern.Jet.Stat.Descriptive.Frequencies(sorted, distinct, null); // since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin if (distinct.Count > 0) { distinct.Add(distinct[distinct.Count - 1] + epsilon); } distinct.TrimToSize(); Hep.Aida.IAxis xaxis = new Hep.Aida.Ref.VariableAxis(distinct.ToArray()); // compute distinct values of y vals = y.ToArray(); sorted.Sort(); Cern.Jet.Stat.Descriptive.Frequencies(sorted, distinct, null); // since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin if (distinct.Count > 0) { distinct.Add(distinct[distinct.Count - 1] + epsilon); } distinct.TrimToSize(); Hep.Aida.IAxis yaxis = new Hep.Aida.Ref.VariableAxis(distinct.ToArray()); // compute distinct values of z vals = z.ToArray(); sorted.Sort(); Cern.Jet.Stat.Descriptive.Frequencies(sorted, distinct, null); // since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin if (distinct.Count > 0) { distinct.Add(distinct[distinct.Count - 1] + epsilon); } distinct.TrimToSize(); Hep.Aida.IAxis zaxis = new Hep.Aida.Ref.VariableAxis(distinct.ToArray()); Hep.Aida.IHistogram3D histo = new Hep.Aida.Ref.Histogram3D("Cube", xaxis, yaxis, zaxis); return(Histogram(histo, x, y, z, weights)); }