/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.jlab.groot.matrix;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jlab.groot.data.DataVector;
import org.jlab.groot.data.H1F;
import org.jlab.groot.math.Axis;
import org.jlab.groot.ui.TCanvas;

/**
 *
 * @author gavalian
 */
public class SparseVectorGrid {
    
    SparseIndex               indexer;
    HashMap   binMap;
    private int  vectorSize   = 1;
    private List  gridAxis = new ArrayList();
    
    public SparseVectorGrid(){
        
    }
    
    public SparseVectorGrid(int[] bins){
        this.indexer = new SparseIndex(bins);
        this.binMap  = new HashMap();
        for(int i = 0; i < bins.length; i++) gridAxis.add(new Axis(bins[i],0.0,1.0));
    }
    
    public SparseVectorGrid(int size, int[] bins){
        this.vectorSize = size;
        this.indexer = new SparseIndex(bins);
        this.binMap = new HashMap();
        for(int i = 0; i < bins.length; i++) gridAxis.add(new Axis(bins[i],0.0,1.0));
    }
    
    public HashMap getGrid(){ return binMap;}
    
    public int getVectorSize(){
        return this.vectorSize;
    }
    
    
    public void addBin(int[] index){
        Long key = indexer.getKey(index);
        binMap.put(key, new DataVector(this.vectorSize));
    }
    
    public void addBin(DataVector vec, int[] index){
        Long key = indexer.getKey(index);
        binMap.put(key, vec);
    }
    
    public Axis getAxis(int index){
        return this.gridAxis.get(index);
    }
    /**
     * sets names for all the axis.
     * @param names array of names to set axis titles
     */
    public void setAxisNames(String[] names){
        if(names.length!=this.gridAxis.size()){
            System.out.println("[setAxisNames] ERROR : Names do not have same dimension as axis");
        } else {
            for(int i = 0; i < names.length; i++) this.gridAxis.get(i).setTitle(names[i]);
        }
    }
    /**
     * fills the array of indices with bin values taken from the axis. 
     * @param values axis values
     * @param index returned index for each dimension
     * @return returns true if all indices are within the bounds, false otherwise
     */
    public boolean getBinsByAxis(double[] values, int[] index){
        boolean flag = true;
        for(int i = 0; i < values.length; i++){
            index[i] = this.gridAxis.get(i).getBin(values[i]);
            if(index[i]<0||index[i]>=this.gridAxis.get(i).getNBins())
                flag = false;
        }  
        return flag;
    }    
    /**
     * fill the grid element 0 with weight of 1.0
     * @param array values along the axis
     */
    public void fill(double[] array){
        this.fill(array,0,1.0);
    }
    /**
     * fill the grid with values from array for element = order
     * with default weight of 1.0
     * @param array values along the axis
     * @param order element index
     */
    public void fill(double[] array, int order){
        this.fill(array,order,1.0);
    }
    /**
     * increment the value of the particular bin, the bin
     * is determined by axis. order is index in the array.
     * @param array values along the axis
     * @param order element index
     * @param weight increment amount
     */
    public void fill(double[] array, int order, double weight){
        int[] index = new int[array.length];
        boolean status = this.getBinsByAxis(array, index);
        if(status==true){
            DataVector vec = getBinVector(index);
            double value = vec.getValue(order);
            vec.set(order, value + weight);
        }
    }
    /**
     * returns a vector for a bin, if the entry does not exist
     * a NULL will be returned. 
     * @param index
     * @return 
     */
    public DataVector getBin(int[] index){
        Long key = indexer.getKey(index);
        if(binMap.containsKey(key)==true) return binMap.get(key);
        return null;
    }
    /**
     * returns vector for particular bin, if the entry does not exist
     * in the map, it creates a new one.
     * @param index
     * @return 
     */
    private DataVector getBinVector(int[] index){
        Long key = indexer.getKey(index);
        if(binMap.containsKey(key)==false){            
            binMap.put(key, new DataVector(vectorSize));
        } 
        return binMap.get(key);
    }
    /**
     * returns ":" separated list of axis names
     * @return string with all axis names
     */
    public String getAxisNamesString(){
        StringBuilder str = new StringBuilder();
        str.append(this.gridAxis.get(0).getTitle());
        for(int i = 1; i < this.gridAxis.size(); i++){
            str.append(":");
            str.append(gridAxis.get(i).getTitle());
        }
        return str.toString();
    }
    
    public void addBinContent(int order, double value, int[] index){
        Long key = indexer.getKey(index);
        DataVector  vec = getBinVector(index);
        //System.out.println(" setting value = " +  (value + vec.getValue(order)));
        vec.set(order, value + vec.getValue(order));
    }
    
    public void setBinContent(int order, double value, int[] index){
        Long key = indexer.getKey(index);
        DataVector  vec = getBinVector(index);
        vec.set(order, value);
    }
    
    public double getBinContent(int order, int[] index){
        DataVector vec = this.getBin(index);
        if(vec==null) return 0.0;
        return vec.getValue(order);
    }
    
    public SparseIndex  getIndexer(){
        return indexer;
    }
    
    public double integral(int order){        
        double summ = 0.0;
        for(Map.Entry  entry : this.binMap.entrySet()){
            summ += entry.getValue().getValue(order);
        }
        return summ;
    }
    
    public H1F slice(int dim, int order, int[] bmin, int[] bmax){
        int bins = this.indexer.getBinsPerAxis()[dim];
        H1F h1 = new H1F("h1",bins,0.0,1.0);
        int[] keyBins = new int[indexer.getRank()];
        
        for(Map.Entry  entry : this.binMap.entrySet()){
            boolean doesFill = true;
            
            indexer.getIndex(entry.getKey(), keyBins);
        
            int nbin = keyBins[dim];
            
            for(int i = 0; i < keyBins.length;i++){
                if( (keyBins[i]bmax[i])&&i!=dim) doesFill = false;
            }
            
            if(doesFill==true){
                /*System.out.print("filling key bins : ");
                for(int i = 0; i < keyBins.length; i++) System.out.print(" " + keyBins[i]);
                System.out.println();*/
                double center = h1.getXaxis().getBinCenter(nbin);
                h1.fill(center,entry.getValue().getValue(order));
            }
        }
        h1.setFillColor(43);
        return h1;
    }
    
    public H1F projection(int dim, int order){
        int bins = this.indexer.getBinsPerAxis()[dim];
        H1F h1 = new H1F("h1",bins,0.0,1.0);
        
        int[] keyBins = new int[indexer.getRank()];
        
        for(Map.Entry  entry : this.binMap.entrySet()){
            indexer.getIndex(entry.getKey(), keyBins);
            int nbin = keyBins[dim];
            double center = h1.getXaxis().getBinCenter(nbin);
            h1.fill(center,entry.getValue().getValue(order));
        }
        h1.setFillColor(43);
        return h1;
    }
    
    public int getNumberOfBins(){
        int nbins = 1;
        for(int i = 0; i < this.gridAxis.size(); i++){
            nbins *= this.gridAxis.get(i).getNBins();
        }
        return nbins;
    }
    
    public void show(){
        
        StringBuilder str = new StringBuilder();        
        int        nbins = this.getNumberOfBins();
        int     nentries = this.binMap.size();
        double populated = ((double) nentries)/nbins;
        
        str.append(String.format("SPARSE GRID  : NBINS = %12d ,  ENTRIES = %12d, POPULATION = %8.1f %%\n", 
                nbins,nentries, 100*populated));
        str.append(String.format("GRID COLUMNS : %-12d \n",this.vectorSize));
        str.append(String.format("INDEXER      : %s\n", this.getIndexer().toString())); 
        for(int i = 0; i < this.vectorSize; i++){
            str.append(String.format("  ORDER %4d : INTEGRAL = %e\n", i,this.integral(i)));
        }
        
        for(int i = 0; i < this.gridAxis.size(); i++){
            str.append(String.format("AXIS  # %2d (%12s) : %5d %12.5f %12.5f\n", i,
                    this.gridAxis.get(i).getTitle(),
                    this.gridAxis.get(i).getNBins(),
                    this.gridAxis.get(i).min(),
                    this.gridAxis.get(i).max()                    
                    ));
        }
        
        System.out.println(str.toString());
    }
    
    public static void main(String[] args){
        
        SparseVectorGrid grid = new SparseVectorGrid(2,new int[]{10,20,30});
        grid.addBinContent(0, 12.0, new int[]{1,2,3});
        grid.addBinContent(1, 24.0, new int[]{1,2,3});
        grid.show();
        
        H1F h1 = grid.projection(2,1);
        TCanvas c1 = new TCanvas("grid",500,500);
        c1.draw(h1);
    }
}

 

Ads help maintain this website.