1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package ubic.basecode.util.r;
20  
21  import org.apache.commons.collections4.Transformer;
22  import org.apache.commons.collections4.functors.StringValueTransformer;
23  import org.apache.commons.lang3.ArrayUtils;
24  import org.apache.commons.lang3.RandomStringUtils;
25  import org.apache.commons.lang3.StringUtils;
26  import org.rosuda.REngine.*;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  import ubic.basecode.dataStructure.matrix.DoubleMatrix;
30  import ubic.basecode.dataStructure.matrix.ObjectMatrix;
31  import ubic.basecode.dataStructure.matrix.ObjectMatrixImpl;
32  import ubic.basecode.math.linearmodels.LinearModelSummary;
33  import ubic.basecode.math.linearmodels.OneWayAnovaResult;
34  import ubic.basecode.math.linearmodels.TwoWayAnovaResult;
35  import ubic.basecode.util.Configuration;
36  
37  import java.io.BufferedReader;
38  import java.io.IOException;
39  import java.io.InputStream;
40  import java.io.InputStreamReader;
41  import java.util.*;
42  
43  
44  
45  
46  
47  
48  
49  public abstract class AbstractRClient implements RClient {
50  
51      protected static Logger log = LoggerFactory.getLogger( AbstractRClient.class );
52  
53      
54  
55  
56  
57      public static String variableIdentityNumber( Object ob ) {
58          return Integer.toString( Math.abs( ob.hashCode() + 1 ) ) + RandomStringUtils.insecure().nextAlphabetic( 6 );
59      }
60  
61      
62  
63  
64  
65  
66  
67  
68      private static double[] unrollMatrix( double[][] matrix ) {
69          int rows = matrix.length;
70          int cols = matrix[0].length;
71          double[] unrolledMatrix = new double[rows * cols];
72  
73          int k = 0;
74          for ( int i = 0; i < rows; i++ ) {
75              for ( int j = 0; j < cols; j++ ) {
76                  unrolledMatrix[k] = matrix[i][j];
77                  k++;
78              }
79          }
80          return unrolledMatrix;
81      }
82  
83      
84  
85  
86  
87  
88  
89  
90      private static double[] unrollMatrix( DoubleMatrix<?, ?> matrix ) {
91          
92          
93          
94          
95          int rows = matrix.rows();
96          int cols = matrix.columns();
97          double[] unrolledMatrix = new double[rows * cols];
98  
99          int k = 0;
100         for ( int i = 0; i < rows; i++ ) {
101             for ( int j = 0; j < cols; j++ ) {
102                 unrolledMatrix[k] = matrix.get( i, j );
103                 k++;
104             }
105         }
106         return unrolledMatrix;
107     }
108 
109     
110 
111 
112 
113 
114     @Override
115     public String assignFactor( List<String> strings ) {
116         String variableName = "f." + variableIdentityNumber( strings );
117         return assignFactor( variableName, strings );
118     }
119 
120     
121 
122 
123 
124 
125     @Override
126     public String assignFactor( String factorName, List<String> list ) {
127         String l = assignStringList( list );
128         this.voidEval( factorName + "<-factor(" + l + ")" );
129         return factorName;
130     }
131 
132     
133 
134 
135 
136 
137     @Override
138     public String assignMatrix( double[][] matrix ) {
139         String matrixVarName = "Matrix_" + variableIdentityNumber( matrix );
140         log.debug( "Assigning matrix with variable name " + matrixVarName );
141         int rows = matrix.length;
142         int cols = matrix[0].length;
143         if ( rows == 0 || cols == 0 ) throw new IllegalArgumentException( "Empty matrix?" );
144         double[] unrolledMatrix = unrollMatrix( matrix );
145         this.assign( "U" + matrixVarName, unrolledMatrix ); 
146         this.voidEval( matrixVarName + "<-matrix(" + "U" + matrixVarName + ", nrow=" + rows + " , ncol=" + cols
147                 + ", byrow=TRUE)" );
148         this.voidEval( "rm(U" + matrixVarName + ")" ); 
149 
150         return matrixVarName;
151     }
152 
153     
154 
155 
156 
157 
158     @Override
159     public String assignMatrix( DoubleMatrix<?, ?> matrix ) {
160         return assignMatrix( matrix, StringValueTransformer.stringValueTransformer() );
161     }
162 
163     
164 
165 
166 
167 
168 
169     @Override
170     public String assignMatrix( DoubleMatrix<?, ?> matrix, Transformer rowNameExtractor ) {
171         String matrixVarName = "Matrix_" + variableIdentityNumber( matrix );
172         log.debug( "Assigning matrix with variable name " + matrixVarName );
173         int rows = matrix.rows();
174         int cols = matrix.columns();
175         if ( rows == 0 || cols == 0 ) throw new IllegalArgumentException( "Empty matrix?" );
176         double[] unrolledMatrix = unrollMatrix( matrix );
177         assert ( unrolledMatrix != null );
178         this.assign( "U" + matrixVarName, unrolledMatrix );
179         this.voidEval( matrixVarName + "<-matrix(" + "U" + matrixVarName + ", nrow=" + rows + ", ncol=" + cols
180                 + ", byrow=TRUE)" );
181         this.voidEval( "rm(U" + matrixVarName + ")" ); 
182 
183         if ( matrix.hasColNames() && matrix.hasRowNames() )
184             assignRowAndColumnNames( matrix, matrixVarName, rowNameExtractor );
185         return matrixVarName;
186     }
187 
188     
189 
190 
191 
192 
193     @Override
194     public String assignStringList( List<?> strings ) {
195         String variableName = "stringList." + variableIdentityNumber( strings );
196 
197         Object[] array = strings.toArray();
198         String[] sa = new String[array.length];
199         for ( int i = 0; i < array.length; i++ ) {
200             sa[i] = array[i].toString();
201         }
202 
203         assign( variableName, sa );
204         return variableName;
205     }
206 
207     
208 
209 
210 
211 
212     @Override
213     public boolean booleanDoubleArrayEval( String command, String argName, double[] arg ) {
214         this.assign( argName, arg );
215         REXP x = this.eval( command );
216         if ( x.isLogical() ) {
217             try {
218                 REXPLogical b = new REXPLogical( new boolean[1], new REXPList( x.asList() ) );
219                 return b.isTRUE()[0];
220             } catch ( REXPMismatchException e ) {
221                 throw new RuntimeException( e );
222             }
223         }
224         return false;
225     }
226 
227     
228 
229 
230 
231 
232     @Override
233     public String dataFrame( ObjectMatrix<String, String, Object> matrix ) {
234 
235         
236 
237 
238 
239         List<String> colNames = matrix.getColNames();
240         List<String> rowNames = matrix.getRowNames();
241 
242         assert colNames.size() == matrix.columns();
243 
244         String colV = assignStringList( colNames );
245         String rowV = assignStringList( rowNames );
246 
247         List<String> terms = new ArrayList<String>();
248         for ( int j = 0; j < colNames.size(); j++ ) {
249 
250             Object[] column;
251 
252             Object v = matrix.getEntry( 0, j );
253 
254             if ( v instanceof Number ) {
255                 column = new Double[matrix.rows()];
256             } else if ( v instanceof Boolean ) {
257                 column = new String[matrix.rows()];
258             } else if ( v instanceof String ) {
259                 column = new String[matrix.rows()];
260             } else {
261                 throw new IllegalArgumentException( "Sorry, can't make data frame from values of type "
262                         + v.getClass().getName() );
263             }
264 
265             for ( int i = 0; i < matrix.rows(); i++ ) {
266 
267                 Object value = matrix.getEntry( i, j );
268 
269                 if ( matrix.isMissing( i, j ) ) {
270                     column[i] = null;
271                 } else if ( value instanceof Number ) {
272                     column[i] = ( ( Number ) value ).doubleValue();
273                 } else if ( value instanceof Boolean ) {
274                     column[i] = ( ( Boolean ) value ) ? "T" : "F";
275                 } else if ( value instanceof String ) {
276                     column[i] = value;
277                 }
278             }
279 
280             if ( v instanceof Number ) {
281                 assign( colNames.get( j ), ArrayUtils.toPrimitive( ( Double[] ) column ) );
282                 terms.add( colNames.get( j ) );
283             } else if ( v instanceof Boolean ) {
284                 assignFactor( colNames.get( j ), Arrays.asList( ( String[] ) column ) );
285                 terms.add( colNames.get( j ) );
286             } else if ( v instanceof String ) {
287                 assignFactor( colNames.get( j ), Arrays.asList( ( String[] ) column ) );
288                 terms.add( colNames.get( j ) );
289             }
290 
291         }
292 
293         String varName = "df." + variableIdentityNumber( matrix );
294 
295         String command = varName + "<-data.frame(" + StringUtils.join( terms, "," ) + ", row.names=" + rowV + " )";
296         log.debug( command );
297         eval( command );
298         eval( "names(" + varName + ")<-" + colV );
299 
300         return varName;
301 
302     }
303 
304     @Override
305     public ObjectMatrix<String, String, Object> dataFrameEval( String command ) {
306 
307         REXP df = eval( command );
308 
309         try {
310 
311             RList dfl = df.asList();
312 
313             if ( !df.getAttribute( "class" ).asString().equals( "data.frame" ) ) {
314                 throw new IllegalArgumentException( "Command did not return a dataframe" );
315             }
316 
317             String[] rowNames = df.getAttribute( "row.names" ).asStrings();
318             String[] colNames = df.getAttribute( "names" ).asStrings();
319 
320             assert dfl.size() == colNames.length;
321 
322             ObjectMatrix<String, String, Object> result = new ObjectMatrixImpl<String, String, Object>(
323                     rowNames.length, colNames.length );
324 
325             result.setRowNames( Arrays.asList( rowNames ) );
326             result.setColumnNames( Arrays.asList( colNames ) );
327 
328             for ( int i = 0; i < dfl.size(); i++ ) {
329                 REXP column = ( REXP ) dfl.get( i );
330 
331                 if ( column.isNumeric() ) {
332                     double[] asDoubles = column.asDoubles();
333 
334                     for ( int j = 0; j < rowNames.length; j++ ) {
335                         result.set( j, i, asDoubles[j] );
336                     }
337 
338                 } else {
339                     String[] asStrings = column.asStrings();
340 
341                     for ( int j = 0; j < rowNames.length; j++ ) {
342                         result.set( j, i, asStrings[j] );
343                     }
344 
345                 }
346 
347             }
348 
349             return result;
350         } catch ( REXPMismatchException e ) {
351 
352             throw new RuntimeException( e );
353 
354         }
355 
356     }
357 
358     public abstract void disconnect();
359 
360     
361 
362 
363 
364 
365     @Override
366     public double[] doubleArrayDoubleArrayEval( String command, String argName, double[] arg ) {
367         try {
368             this.assign( argName, arg );
369             RList l = this.eval( command ).asList();
370             return l.at( argName ).asDoubles();
371         } catch ( REXPMismatchException e ) {
372             throw new RuntimeException( e );
373         }
374     }
375 
376     
377 
378 
379 
380 
381     @Override
382     public double[] doubleArrayEval( String command ) {
383         REXP r = this.eval( command );
384         if ( r == null ) {
385             return null;
386         }
387 
388         if ( !r.isNumeric() ) {
389             throw new RuntimeException( "Command did not return numbers: " + command + ", result was: " + r );
390         }
391 
392         try {
393             return r.asDoubles();
394         } catch ( REXPMismatchException e ) {
395             throw new RuntimeException( e );
396         }
397     }
398 
399     
400 
401 
402 
403 
404 
405     @Override
406     public double[] doubleArrayTwoDoubleArrayEval( String command, String argName, double[] arg, String argName2,
407             double[] arg2 ) {
408         this.assign( argName, arg );
409         this.assign( argName2, arg2 );
410         try {
411             return this.eval( command ).asDoubles();
412         } catch ( REXPMismatchException e ) {
413             throw new RuntimeException( e );
414         }
415     }
416 
417     
418 
419 
420 
421 
422 
423     @Override
424     public double doubleTwoDoubleArrayEval( String command, String argName, double[] arg, String argName2, double[] arg2 ) {
425         this.assign( argName, arg );
426         this.assign( argName2, arg2 );
427         REXP x = this.eval( command );
428         try {
429             return x.asDouble();
430         } catch ( REXPMismatchException e ) {
431             throw new RuntimeException( e );
432         }
433     }
434 
435     
436 
437 
438 
439 
440     @Override
441     public int[] intArrayEval( String command ) {
442         try {
443             return eval( command ).asIntegers();
444         } catch ( REXPMismatchException e ) {
445             throw new RuntimeException( e );
446         }
447     }
448 
449     
450 
451 
452 
453 
454     @Override
455     @SuppressWarnings({ "unchecked" })
456     public LinearModelSummary linearModel( double[] data, Map<String, List<?>> factors ) {
457 
458         String datName = RandomStringUtils.insecure().nextAlphabetic( 10 );
459         assign( datName, data );
460 
461         for ( String factorName : factors.keySet() ) {
462             List<?> list = factors.get( factorName );
463             if ( list.iterator().next() instanceof String ) {
464                 assignFactor( factorName, ( List<String> ) list );
465             } else {
466                 
467                 List<Double> d = new ArrayList<Double>();
468                 for ( Object object : list ) {
469                     d.add( ( Double ) object );
470                 }
471 
472                 assign( factorName, ArrayUtils.toPrimitive( d.toArray( new Double[] {} ) ) );
473             }
474         }
475 
476         String modelDeclaration = datName + " ~ " + StringUtils.join( factors.keySet(), "+" );
477 
478         String lmName = RandomStringUtils.insecure().nextAlphabetic( 10 );
479         String command = lmName + "<-lm(" + modelDeclaration + ", na.action=na.exclude)";
480         log.debug( command );
481         voidEval( command );
482 
483         REXP lmsum = eval( "summary(" + lmName + ")" );
484         REXP anova = eval( "anova(" + lmName + ")" );
485 
486         try {
487             return new LinearModelSummaryImpl( datName, lmsum, anova, factors.keySet().toArray( new String[] {} ) );
488         } catch ( REXPMismatchException e ) {
489             throw new RuntimeException( e );
490         }
491     }
492 
493     
494 
495 
496 
497 
498     @Override
499     public LinearModelSummary linearModel( double[] data, ObjectMatrix<String, String, Object> d ) {
500 
501         String datName = RandomStringUtils.insecure().nextAlphabetic( 10 );
502         assign( datName, data );
503 
504         String df = dataFrame( d );
505 
506         String varNames = StringUtils.join( d.getColNames(), "+" );
507 
508         String lmName = RandomStringUtils.insecure().nextAlphabetic( 10 );
509         String command = lmName + "<-lm(" + datName + " ~ " + varNames + ", data=" + df + ", na.action=na.exclude)";
510         voidEval( command );
511 
512         REXP lmsum = eval( "summary(" + lmName + ")" );
513         REXP anova = eval( "anova(" + lmName + ")" );
514 
515         try {
516             return new LinearModelSummaryImpl( datName, lmsum, anova, d.getColNames().toArray( new String[] {} ) );
517         } catch ( REXPMismatchException e ) {
518             throw new RuntimeException( e );
519         }
520     }
521 
522     
523 
524 
525     @Override
526     public List<?> listEval( Class<?> listEntryType, String command ) {
527 
528         REXP rexp = this.eval( command );
529 
530         List<Object> result = new ArrayList<Object>();
531         try {
532             if ( !rexp.isVector() ) {
533                 throw new IllegalArgumentException( "Command did not return some kind of vector" );
534             }
535 
536             if ( rexp instanceof REXPInteger ) {
537                 log.debug( "integer" );
538                 double[][] asDoubleMatrix = rexp.asDoubleMatrix();
539                 for ( double[] ds : asDoubleMatrix ) {
540                     result.add( ds );
541                 }
542 
543                 if ( rexp instanceof REXPFactor ) {
544                     log.info( "factor" );
545                     
546                 }
547             } else if ( rexp instanceof REXPGenericVector ) {
548                 log.debug( "generic" );
549                 REXPGenericVector v = ( REXPGenericVector ) rexp;
550                 List<?> tmp = new ArrayList<Object>( v.asList().values() );
551 
552                 if ( tmp.size() == 0 ) return tmp;
553 
554                 for ( Object t : tmp ) {
555                     String clazz = ( ( REXP ) t ).getAttribute( "class" ).asString();
556                     
557 
558 
559                     if ( clazz.equals( "htest" ) ) {
560                         try {
561                             result.add( new HTest( ( ( REXP ) t ).asList() ) );
562                         } catch ( REXPMismatchException e ) {
563                             result.add( new HTest() );
564                         }
565                     } else if ( clazz.equals( "lm" ) ) {
566                         throw new UnsupportedOperationException();
567                     } else {
568                         result.add( new HTest() ); 
569                     }
570                     
571 
572 
573                 }
574 
575             } else if ( rexp instanceof REXPDouble ) {
576                 log.debug( "double" );
577                 double[][] asDoubleMatrix = rexp.asDoubleMatrix();
578                 for ( double[] ds : asDoubleMatrix ) {
579                     result.add( ds );
580                 }
581 
582             } else if ( rexp instanceof REXPList ) {
583                 log.debug( "list" );
584                 if ( rexp.isPairList() ) {
585                     
586                 }
587 
588                 if ( rexp.isLanguage() ) {
589                     throw new UnsupportedOperationException( "Don't know how to deal with vector type of "
590                             + rexp.getClass().getName() );
591                 }
592                 log.debug( rexp.getClass().getName() );
593                 result = new ArrayList<Object>( rexp.asList().values() );
594             } else {
595                 throw new UnsupportedOperationException( "Don't know how to deal with vector type of "
596                         + rexp.getClass().getName() );
597             }
598 
599             return result;
600         } catch ( REXPMismatchException e ) {
601             throw new RuntimeException( e );
602         }
603 
604     }
605 
606     
607 
608 
609 
610 
611     @Override
612     public boolean loadLibrary( String libraryName ) {
613         try {
614 
615             String userLibPath = Configuration.getString( "rlibpath" );
616             if ( StringUtils.isNotBlank( userLibPath ) ) {
617                 voidEval( ".libPaths(" + userLibPath + ")" );
618             }
619             
620 
621             List<String> libraries = stringListEval( "installed.packages()[,1]" );
622             if ( !libraries.contains( libraryName ) ) {
623                 return false;
624             }
625         } catch ( Exception e ) {
626             
627 
628 
629             log.warn( "Was unable to check for installed library before attempting to load it." );
630         }
631 
632         try {
633             voidEval( "library(" + libraryName + ")" );
634             return true;
635         } catch ( Exception e ) {
636             return false;
637         }
638     }
639 
640     
641 
642 
643 
644 
645     @Override
646     public OneWayAnovaResult oneWayAnova( double[] data, List<String> factor ) {
647         String f = assignFactor( factor );
648         StringBuffer command = new StringBuffer();
649 
650         assign( "foo", data );
651 
652         String modelDeclaration;
653 
654         modelDeclaration = "foo  ~ " + f;
655 
656         command.append( "anova(aov(" + modelDeclaration + "))" );
657 
658         REXP eval = eval( command.toString() );
659 
660         try {
661             return new OneWayAnovaResultImpl( "foo", eval );
662         } catch ( REXPMismatchException e ) {
663             throw new RuntimeException( e );
664         }
665     }
666 
667     
668 
669 
670 
671 
672     @Override
673     public Map<String, OneWayAnovaResult> oneWayAnovaEval( String command ) {
674         REXP rawResult = this.eval( command );
675 
676         if ( rawResult == null ) {
677             return null;
678         }
679 
680         Map<String, OneWayAnovaResult> result = new HashMap<String, OneWayAnovaResult>();
681         try {
682             RList mainList = rawResult.asList();
683             if ( mainList == null ) {
684                 return null;
685             }
686 
687             log.debug( mainList.size() + " results." );
688 
689             for ( int i = 0; i < mainList.size(); i++ ) {
690 
691                 REXP anovaTable = mainList.at( i );
692 
693                 String elementIdentifier = mainList.keyAt( i );
694 
695                 assert elementIdentifier != null;
696 
697                 if ( log.isDebugEnabled() ) log.debug( "Key: " + elementIdentifier );
698 
699                 if ( !anovaTable.isList() || !anovaTable.hasAttribute( "row.names" ) ) {
700                     log.debug( "No anovaresult for " + elementIdentifier );
701                     result.put( elementIdentifier, new OneWayAnovaResultImpl( elementIdentifier ) );
702                     continue;
703                 }
704 
705                 result.put( elementIdentifier, new OneWayAnovaResultImpl( elementIdentifier, anovaTable ) );
706 
707             }
708         } catch ( REXPMismatchException e ) {
709             throw new RuntimeException( e );
710         }
711 
712         return result;
713 
714     }
715 
716     
717 
718 
719 
720 
721     @Override
722     public void remove( String variableName ) {
723         this.voidEval( "rm(" + variableName + ")" );
724     }
725 
726     
727 
728 
729 
730 
731     @Override
732     public Map<String, LinearModelSummary> rowApplyLinearModel( String dataMatrixVarName, String modelFormula,
733             String[] factorNames ) {
734 
735         String lmres = "lmlist." + RandomStringUtils.insecure().nextAlphanumeric( 10 );
736 
737         log.info( "Starting model fitting ..." );
738 
739         loadScript( this.getClass().getResourceAsStream( "/ubic/basecode/util/r/linearModels.R" ) );
740 
741         String command = lmres + "<-rowlm(" + modelFormula + ", data.frame(" + dataMatrixVarName + ") )";
742 
743         log.debug( command );
744         this.voidEval( command );
745 
746         log.info( "Model fits complete, summarizing ..." );
747         REXP rawLmSummaries = this.eval( "lapply(" + lmres + ", function(x){ try(summary(x), silent=T)})" );
748 
749         if ( rawLmSummaries == null ) {
750             log.warn( "No results from apply(... lm)" );
751             return null;
752         }
753 
754         log.info( "Summaries done, doing hypothesis tests ..." );
755         
756         REXP rawAnova = this.eval( "lapply(" + lmres + ", function(x){ try(anova(x), silent=T)})" );
757 
758         Map<String, LinearModelSummary> result = new HashMap<String, LinearModelSummary>();
759         try {
760             log.info( "Processing the results ..." );
761 
762             RList rawLmList = rawLmSummaries.asList();
763             if ( rawLmList == null ) {
764                 log.warn( "Raw lm summary results were null" );
765                 return null;
766             }
767 
768             RList rawAnovaList = rawAnova.asList();
769             if ( rawAnovaList == null ) {
770                 return null;
771             }
772 
773             log.debug( rawLmList.size() + " results." );
774 
775             assert rawLmList.size() == rawAnovaList.size();
776 
777             for ( int i = 0; i < rawLmList.size(); i++ ) {
778 
779                 REXP lmSummary = rawLmList.at( i );
780                 REXP anova = rawAnovaList.at( i );
781 
782                 String elementIdentifier = rawLmList.keyAt( i );
783 
784                 assert elementIdentifier != null;
785                 assert elementIdentifier.equals( rawAnovaList.keyAt( i ) );
786 
787                 if ( log.isDebugEnabled() ) log.debug( "Key: " + elementIdentifier );
788 
789                 if ( !lmSummary.isList() || !lmSummary.getAttribute( "class" ).asString().equals( "summary.lm" ) ) {
790                     log.debug( "No lm for " + elementIdentifier );
791                     result.put( elementIdentifier, new LinearModelSummaryImpl( elementIdentifier ) );
792                 } else {
793                     LinearModelSummary linearModelSummary = new LinearModelSummaryImpl( elementIdentifier, lmSummary, anova, factorNames );
794                     result.put( elementIdentifier, linearModelSummary );
795                 }
796 
797             }
798         } catch ( REXPMismatchException e ) {
799             throw new RuntimeException( e );
800         }
801 
802         return result;
803     }
804 
805     
806 
807 
808 
809 
810     @Override
811     public String stringEval( String command ) {
812         try {
813             return this.eval( command ).asString();
814         } catch ( REXPMismatchException e ) {
815             throw new RuntimeException( e );
816         }
817     }
818 
819     
820 
821 
822 
823 
824     @Override
825     public List<String> stringListEval( String command ) {
826         try {
827             REXP eval = this.eval( command );
828 
829             RList v;
830             List<String> results = new ArrayList<String>();
831             if ( eval instanceof REXPString ) {
832                 String[] strs = ( ( REXPString ) eval ).asStrings();
833                 for ( String string : strs ) {
834                     results.add( string );
835                 }
836             } else {
837                 v = eval.asList();
838                 for ( Iterator<?> it = v.iterator(); it.hasNext(); ) {
839                     results.add( ( ( REXPString ) it.next() ).asString() );
840                 }
841             }
842 
843             return results;
844         } catch ( REXPMismatchException e ) {
845             throw new RuntimeException( e );
846         }
847     }
848 
849     
850 
851 
852 
853 
854     @Override
855     public TwoWayAnovaResult twoWayAnova( double[] data, List<String> factor1, List<String> factor2,
856             boolean includeInteraction ) {
857 
858         String factorA = assignFactor( factor1 );
859         String factorB = assignFactor( factor2 );
860         StringBuffer command = new StringBuffer();
861 
862         assign( "foo", data );
863 
864         String modelDeclaration;
865 
866         if ( includeInteraction ) {
867             modelDeclaration = "foo  ~ " + factorA + "*" + factorB;
868         } else {
869             modelDeclaration = "foo  ~ " + factorA + "+" + factorB;
870         }
871 
872         command.append( "anova(aov(" + modelDeclaration + "))" );
873 
874         REXP eval = eval( command.toString() );
875 
876         try {
877             return new TwoWayAnovaResultImpl( "foo", eval );
878         } catch ( REXPMismatchException e ) {
879             throw new RuntimeException( e );
880         }
881     }
882 
883     
884 
885 
886 
887 
888     @Override
889     public Map<String, TwoWayAnovaResult> twoWayAnovaEval( String command, boolean withInteractions ) {
890         REXP rawResult = this.eval( command );
891 
892         if ( rawResult == null ) {
893             return null;
894         }
895 
896         Map<String, TwoWayAnovaResult> result = new HashMap<String, TwoWayAnovaResult>();
897         try {
898             RList mainList = rawResult.asList();
899             if ( mainList == null ) {
900                 return null;
901             }
902 
903             log.debug( mainList.size() + " results." );
904 
905             for ( int i = 0; i < mainList.size(); i++ ) {
906 
907                 REXP anovaTable = mainList.at( i );
908 
909                 String elementIdentifier = mainList.keyAt( i );
910 
911                 assert elementIdentifier != null;
912 
913                 if ( log.isDebugEnabled() ) log.debug( "Key: " + elementIdentifier );
914 
915                 if ( !anovaTable.isList() || !anovaTable.hasAttribute( "row.names" ) ) {
916                     log.debug( "No anovaresult for " + elementIdentifier );
917                     result.put( elementIdentifier, new TwoWayAnovaResultImpl( elementIdentifier ) );
918                     continue;
919                 }
920 
921                 result.put( elementIdentifier, new TwoWayAnovaResultImpl( elementIdentifier, anovaTable ) );
922 
923             }
924         } catch ( REXPMismatchException e ) {
925             throw new RuntimeException( e );
926         }
927 
928         return result;
929 
930     }
931 
932     
933 
934 
935 
936 
937 
938     protected void loadScript( InputStream is ) {
939         try {
940 
941             BufferedReader reader = new BufferedReader( new InputStreamReader( is ) );
942             String line = null;
943             StringBuilder buf = new StringBuilder();
944             while ( ( line = reader.readLine() ) != null ) {
945                 if ( line.startsWith( "#" ) || StringUtils.isBlank( line ) ) {
946                     continue;
947                 }
948                 buf.append( StringUtils.trim( line ) + "\n" );
949             }
950             is.close();
951             log.debug( buf.toString() );
952             this.voidEval( buf.toString() );
953 
954         } catch ( IOException e ) {
955             throw new RuntimeException( e );
956         }
957     }
958 
959     
960 
961 
962 
963 
964 
965     private void assignRowAndColumnNames( DoubleMatrix<?, ?> matrix, String matrixVarName, Transformer rowNameExtractor ) {
966 
967         List<Object> rown = new ArrayList<Object>();
968         for ( Object o : matrix.getRowNames() ) {
969             rown.add( rowNameExtractor.transform( o ) );
970         }
971 
972         String rowNameVar = assignStringList( rown );
973         String colNameVar = assignStringList( matrix.getColNames() );
974 
975         String dimcmd = "dimnames(" + matrixVarName + ")<-list(" + rowNameVar + ", " + colNameVar + ")";
976         this.voidEval( dimcmd );
977     }
978 
979 }