View Javadoc
1   /*
2    * The baseCode project
3    * 
4    * Copyright (c) 2006 University of British Columbia
5    * 
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *       http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   *
18   */
19  package ubic.basecode.dataStructure.matrix;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.Vector;
24  
25  import org.apache.commons.collections4.CollectionUtils;
26  import org.apache.commons.lang3.ArrayUtils;
27  
28  import cern.colt.list.DoubleArrayList;
29  import cern.colt.list.IntArrayList;
30  import cern.colt.matrix.DoubleMatrix1D;
31  
32  /**
33   * A sparse matrix class where the rows are ragged and compressed.
34   * 
35   * @author pavlidis
36   * 
37   */
38  public class SparseRaggedDoubleMatrix<R, C> extends DoubleMatrix<R, C> {
39  
40      private static final long serialVersionUID = -8911689395488681312L;
41  
42      int columns = 0;
43  
44      private boolean isDirty = true;
45      private Vector<List<Double>> matrix;
46  
47      public SparseRaggedDoubleMatrix() {
48          matrix = new Vector<List<Double>>();
49      }
50  
51      /**
52       * @param matrix1D
53       */
54      public void addRow( R name, DoubleMatrix1D matrix1D ) {
55          List<Double> row = new ArrayList<Double>();
56          CollectionUtils.addAll( row, ArrayUtils.toObject( matrix1D.toArray() ) );
57          matrix.add( row );
58          this.setRowName( name, matrix.size() - 1 );
59          isDirty = true;
60      }
61  
62      /**
63       * @param name
64       * @param indexes
65       * @param values
66       */
67      public void addRow( R name, IntArrayList indexes, DoubleArrayList values ) {
68          List<Double> row = new ArrayList<Double>();
69          CollectionUtils.addAll( row, ArrayUtils.toObject( values.elements() ) );
70          matrix.add( row );
71          this.setRowName( name, matrix.size() - 1 );
72          isDirty = true;
73      }
74  
75      /**
76       * @return double[][]
77       */
78      @Override
79      public double[][] asArray() {
80          double[][] result = new double[rows()][];
81          for ( int i = 0; i < rows(); i++ ) {
82              result[i] = getRow( i );
83          }
84          return result;
85      }
86  
87      /**
88       * Returns the size of the widest row.
89       * 
90       * @see basecode.dataStructure.matrix.Matrix2D#columns()
91       */
92      @Override
93      public int columns() {
94  
95          if ( !isDirty ) {
96              return columns;
97          }
98  
99          int max = 0;
100         for ( List<Double> element2 : matrix ) {
101             int value = element2.size();
102             if ( value > max ) {
103                 max = value;
104             }
105 
106         }
107 
108         columns = max;
109         isDirty = false;
110         return columns;
111     }
112 
113     /*
114      * (non-Javadoc)
115      * 
116      * @see ubic.basecode.dataStructure.matrix.DoubleMatrixNamed#copy()
117      */
118     @Override
119     public DoubleMatrix<R, C> copy() {
120         DoubleMatrix<R, C> returnval = new SparseRaggedDoubleMatrix<R, C>();
121 
122         for ( int i = 0; i < this.rows(); i++ ) {
123             returnval.setRowName( this.getRowName( i ), i );
124             for ( int j = 0; j < this.columns(); j++ ) {
125                 if ( i == 0 ) {
126                     returnval.setColumnName( this.getColName( j ), j );
127                 }
128                 returnval.set( i, j, this.get( i, j ) );
129             }
130         }
131         return returnval;
132 
133     }
134 
135     /**
136      * @param row
137      * @param column
138      * @return
139      */
140     @Override
141     public double get( int i, int j ) {
142         // return matrix.get( i ).get( j );
143         if ( matrix.get( i ).size() < j + 1 ) {
144             return 0.0;
145         }
146         return matrix.get( i ).get( j );
147     }
148 
149     /*
150      * (non-Javadoc)
151      * 
152      * @see basecode.dataStructure.matrix.NamedMatrix#getColObj(int)
153      */
154     @Override
155     public Double[] getColObj( int col ) {
156         Double[] result = new Double[rows()];
157         for ( int i = 0; i < rows(); i++ ) {
158             result[i] = get( i, col );
159         }
160         return result;
161     }
162 
163     @Override
164     public DoubleMatrix<R, C> getColRange( int startCol, int endCol ) {
165         super.checkColRange( startCol, endCol );
166 
167         DoubleMatrix<R, C> returnval = new SparseRaggedDoubleMatrix<R, C>();
168 
169         for ( int j = 0, m = this.rows(); j < m; j++ ) {
170             if ( j == 0 ) {
171                 R rowName = this.getRowName( j );
172                 returnval.setRowName( rowName, j );
173             }
174             int k = 0;
175             List<Double> row = this.matrix.get( j );
176 
177             for ( int i = startCol; i <= endCol && i < row.size(); i++ ) {
178                 C colName = this.getColName( i );
179                 if ( colName != null ) {
180                     returnval.setColumnName( colName, k );
181                 }
182                 returnval.set( j, k, this.get( j, i ) );
183                 k++;
184             }
185 
186         }
187         return returnval;
188     }
189 
190     /*
191      * (non-Javadoc)
192      * 
193      * @see basecode.dataStructure.matrix.DoubleMatrixNamed#getColumn(int)
194      */
195     @Override
196     public double[] getColumn( int col ) {
197         double[] result = new double[rows()];
198         for ( int i = 0; i < rows(); i++ ) {
199             result[i] = get( i, col );
200         }
201         return result;
202     }
203 
204     @Override
205     public Double getObject( int row, int col ) {
206         return new Double( get( row, col ) );
207     }
208 
209     /*
210      * (non-Javadoc)
211      * 
212      * @see basecode.dataStructure.matrix.AbstractNamedDoubleMatrix#getRow(int)
213      */
214     @Override
215     public double[] getRow( int i ) {
216         return ArrayUtils.toPrimitive( matrix.get( i ).toArray( new Double[] {} ) );
217     }
218 
219     /**
220      * This gives just the list of values in the row - make sure this is what you want. It does not include the zero
221      * values.
222      * 
223      * @param row
224      * @return
225      */
226     @Override
227     public DoubleArrayList getRowArrayList( int row ) {
228         DoubleArrayList returnVal = new DoubleArrayList();
229 
230         for ( Double d : matrix.get( row ) ) {
231             if ( d != 0.0 ) {
232                 returnVal.add( d );
233             }
234         }
235 
236         return returnVal;
237     }
238 
239     /*
240      * (non-Javadoc)
241      * 
242      * @see basecode.dataStructure.matrix.NamedMatrix#getRowObj(int)
243      */
244     @Override
245     public Double[] getRowObj( int i ) {
246         Double[] result = new Double[columns()];
247 
248         double[] row = getRow( i );
249 
250         for ( int j = 0; j < columns(); j++ ) {
251             result[i] = new Double( row[j] );
252         }
253         return result;
254     }
255 
256     /*
257      * (non-Javadoc)
258      * 
259      * @see ubic.basecode.dataStructure.matrix.Matrix2D#getRowRange(int, int)
260      */
261     @Override
262     public DoubleMatrix<R, C> getRowRange( int startRow, int endRow ) {
263         super.checkRowRange( startRow, endRow );
264 
265         DoubleMatrix<R, C> returnval = new SparseRaggedDoubleMatrix<R, C>();
266         int k = 0;
267         for ( int i = startRow; i <= endRow; i++ ) {
268             R rowName = this.getRowName( i );
269             if ( rowName != null ) {
270                 returnval.setRowName( rowName, i );
271             }
272             List<Double> row = this.matrix.get( i );
273             for ( int j = 0, m = row.size(); j < m; j++ ) {
274                 if ( i == 0 ) {
275                     C colName = this.getColName( j );
276                     returnval.setColumnName( colName, j );
277                 }
278                 double value = this.get( i, j );
279                 returnval.set( k, j, value );
280             }
281             k++;
282         }
283         return returnval;
284     }
285 
286     /**
287      * (non-Javadoc) Note that in a sparse matrix, zero values are considered "missing"!
288      * 
289      * @see basecode.dataStructure.matrix.Matrix2D#isMissing(int, int)
290      */
291     @Override
292     public boolean isMissing( int i, int j ) {
293         return get( i, j ) == 0.0;
294     }
295 
296     /*
297      * (non-Javadoc)
298      * 
299      * @see basecode.dataStructure.matrix.NamedMatrix#rows()
300      */
301     @Override
302     public int rows() {
303         return matrix.size();
304     }
305 
306     /*
307      * (non-Javadoc)
308      * 
309      * @see ubic.basecode.dataStructure.matrix.Matrix2D#set(int, int, java.lang.Object)
310      */
311     @Override
312     public void set( int i, int j, Double d ) {
313         if ( matrix.size() <= i ) {
314             for ( int m = matrix.size() - 1; m < i; m++ ) {
315                 matrix.add( new ArrayList<Double>() );
316             }
317         }
318         /*
319          * Fill out rows with zeros.
320          */
321         List<Double> row = matrix.get( i );
322 
323         if ( row.size() <= j ) {
324             for ( int m = row.size() - 1; m < j; m++ ) {
325                 row.add( 0.0 );
326             }
327         }
328         row.set( j, d );
329     }
330 
331     @Override
332     public int size() {
333         return this.rows() * this.columns();
334     }
335 
336     @Override
337     public DoubleMatrix<R, C> subsetColumns( List<C> c ) {
338         throw new UnsupportedOperationException();
339     }
340 
341     /*
342      * (non-Javadoc)
343      * 
344      * @see ubic.basecode.dataStructure.matrix.DoubleMatrix#subsetRows(java.util.Collection)
345      */
346     @Override
347     public DoubleMatrix<R, C> subsetRows( List<R> rowNames ) {
348         DoubleMatrix<R, C> returnval = new SparseRaggedDoubleMatrix<R, C>();
349 
350         int currentRow = 0;
351         for ( int i = 0; i < this.rows(); i++ ) {
352             R rowName = this.getRowName( i );
353             if ( !rowNames.contains( rowName ) ) {
354                 continue;
355             }
356             returnval.setRowName( rowName, currentRow );
357 
358             for ( int j = 0; j < this.columns(); j++ ) {
359                 if ( i == currentRow ) {
360                     C colname = this.getColName( j );
361                     if ( colname != null ) returnval.setColumnName( colname, j );
362                 }
363                 returnval.set( currentRow, j, this.get( i, j ) );
364             }
365             currentRow++;
366         }
367         if ( !returnval.getRowNames().containsAll( rowNames ) ) {
368             throw new IllegalArgumentException( "Invalid rows to select, some are not in the original matrix" );
369         }
370         return returnval;
371     }
372 
373     @Override
374     public DoubleMatrix<C, R> transpose() {
375         throw new UnsupportedOperationException();
376     }
377 
378     @Override
379     public DoubleMatrix1D viewColumn( int column ) {
380         return new RCDoubleMatrix1D( this.getColumn( column ) );
381     }
382 
383     /*
384      * (non-Javadoc)
385      * 
386      * @see basecode.dataStructure.matrix.AbstractNamedDoubleMatrix#viewRow(int)
387      */
388     @Override
389     public DoubleMatrix1D viewRow( int i ) {
390         return new RCDoubleMatrix1D( this.getRow( i ) );
391     }
392 
393 }