/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.das2.qds;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* DataSet for storing sparse data. This is used initially to describe bundles.
* This returns 0 where no data has been set. For example,
*
*sp= SparseDataSet.createQube([2,4])
*sp[2,2]= 1
*print sp[0,0]
*
* @author jbf
*/
public class SparseDataSet extends AbstractDataSet implements WritableDataSet {
int rank;
Map data;
int length0=-1;
int[] qube;
Map length;
/**
* this is private because calling the constructor from Jython won't adapt to PyQDataSet.
* @param rank
*/
private SparseDataSet( int rank ) {
this.rank= rank;
data= new HashMap<>();
length= new HashMap<>();
}
/**
* create the dataset with the given rank. The length of any dimension is explicitly set with the setLength
* method or implicitly by the highest index assigned a value. Note Jython scripts are unable to call the setLength method.
* @param rank number of indeces
* @return a dataset that is empty.
* @see #createRankLen(int, int)
* @see #createQube(int[])
*/
public static SparseDataSet createRank( int rank ) {
return new SparseDataSet(rank);
}
/**
* create the dataset with the given rank and initial length. This
* was introduced because setLength cannot be called from Jython scripts.
* Each record will have length(i) based on the highest index assigned.
* @param rank the result's rank.
* @param len0 the number of records in the result.
* @see #createQube(int[])
* @return SparseDataSet with the given rank.
*/
public static SparseDataSet createRankLen( int rank, int len0 ) {
SparseDataSet result= new SparseDataSet(rank);
result.setLength(len0);
return result;
}
/**
* create the qube dataset with the given dimensions. This
* was introduced because setQube cannot be called from Jython scripts.
* @param qube the index dimensions.
* @return SparseDataSet with the given rank and dimensions based on qube.
*/
public static SparseDataSet createQube( int[] qube ) {
SparseDataSet result= new SparseDataSet(qube.length);
result.setQube(qube);
return result;
}
/**
* set the length of the zeroth dimension. Other dimensions have length set implicitly by the highest value set.
* If this is not set explicitly, then it will be implicit as well.
* @param length
*/
public void setLength( int length ) {
checkImmutable();
this.length0= length;
}
/**
* make this a qube dataset, where all the lengths are the same.
* @param qube
*/
public void setQube( int[] qube ) {
if ( qube.length!=this.rank ) {
throw new IllegalArgumentException("qube length must match rank: "+this.rank );
}
this.qube= Arrays.copyOf( qube,qube.length );
this.length0= qube[0];
}
@Override
public int rank() {
return rank;
}
@Override
public int length() {
if ( length0<0 ) {
throw new IllegalArgumentException("length of SparseDataSet was never set");
}
return this.length0;
}
@Override
public int length(int i) {
if ( this.qube!=null ) {
return this.qube[1];
} else {
Integer len= length.get( String.valueOf(i) );
return len==null? 0 : len;
}
}
@Override
public int length(int i0, int i1) {
if ( this.qube!=null ) {
return this.qube[2];
} else {
Integer len= length.get( String.valueOf(i0)+"_"+String.valueOf(i1) );
return len==null? 0 : len;
}
}
@Override
public int length(int i0, int i1, int i2 ) {
if ( this.qube!=null ) {
return this.qube[3];
} else {
Integer len= length.get( String.valueOf(i0)+"_"+String.valueOf(i1)+"_"+String.valueOf(i2) );
return len==null? 0 : len;
}
}
public void putValue(double d) {
checkImmutable();
data.put( "", d );
}
public void putValue(int i0, double d) {
checkImmutable();
if ( qube==null ) {
length0= Math.max( i0+1, length0 );
}
data.put( String.valueOf(i0), d );
}
public void putValue(int i0, int i1, double d) {
checkImmutable();
if ( qube==null ) {
length0= Math.max( i0+1, length0 );
Integer length1= length.get( String.valueOf(i0) );
if ( length1==null || length1<=i1 ) {
length1= i1+1;
length.put( String.valueOf(i0), length1 );
}
}
data.put( String.valueOf(i0)+"_"+String.valueOf(i1), d );
}
public void putValue(int i0, int i1, int i2, double d) {
checkImmutable();
if ( qube==null ) {
length0= Math.max( i0+1, length0 );
Integer length1= length.get( String.valueOf(i0) );
if ( length1==null || length1<=i1 ) {
length1= i1+1;
length.put( String.valueOf(i0), length1 );
}
Integer length2= length.get( String.valueOf(i0)+"_"+String.valueOf(i1) );
if ( length2==null || length2<=i1 ) {
length2= i2+1;
length.put( String.valueOf(i0)+"_"+String.valueOf(i1), length2 );
}
}
data.put( String.valueOf(i0)+"_"+String.valueOf(i1)+"_"+String.valueOf(i2), d );
}
public void putValue(int i0, int i1, int i2, int i3, double d) {
checkImmutable();
if ( qube==null ) {
length0= Math.max( i0+1, length0 );
Integer length1= length.get( String.valueOf(i0) );
if ( length1==null || length1<=i1 ) {
length1= i1+1;
length.put( String.valueOf(i0), length1 );
}
Integer length2= length.get( String.valueOf(i0)+"_"+String.valueOf(i1) );
if ( length2==null || length2<=i1 ) {
length2= i2+1;
length.put( String.valueOf(i0)+"_"+String.valueOf(i1), length2 );
}
Integer length3= length.get( String.valueOf(i0)+"_"+String.valueOf(i1)+"_"+String.valueOf(i2) );
if ( length3==null || length3<=i1 ) {
length3= i3+1;
length.put( String.valueOf(i0)+"_"+String.valueOf(i1)+"_"+String.valueOf(i2), length3 );
}
}
data.put( String.valueOf(i0)+"_"+String.valueOf(i1)+"_"+String.valueOf(i2)+"_"+String.valueOf(i3), d );
}
@Override
public double value() { // not that this would be useful, but...
if ( rank!=0 ) throw new IllegalArgumentException( "rank mismatch, data is rank "+rank );
Double v= data.get("");
return v==null ? 0 : v;
}
@Override
public double value(int i0) {
if ( rank!=1 ) throw new IllegalArgumentException( "rank mismatch, data is rank "+rank );
Double v= data.get( String.valueOf(i0) );
return v==null ? 0 : v;
}
@Override
public double value(int i0, int i1) {
if ( rank!=2 ) throw new IllegalArgumentException( "rank mismatch, data is rank "+rank );
Double v= data.get( String.valueOf(i0)+"_"+String.valueOf(i1) );
return v==null ? 0 : v;
}
@Override
public double value(int i0, int i1, int i2) {
if ( rank!=3 ) throw new IllegalArgumentException( "rank mismatch, data is rank "+rank );
Double v= data.get( String.valueOf(i0)+"_"+String.valueOf(i1)+"_"+String.valueOf(i2) );
return v==null ? 0 : v;
}
@Override
public double value(int i0, int i1, int i2, int i3) {
if ( rank!=4 ) throw new IllegalArgumentException( "rank mismatch, data is rank "+rank );
Double v= data.get( String.valueOf(i0)+"_"+String.valueOf(i1)+"_"+String.valueOf(i2)+"_"+String.valueOf(i3) );
return v==null ? 0 : v;
}
}