1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package ubic.basecode.math.linearmodels;
21
22 import org.apache.commons.lang3.StringUtils;
23
24 import javax.annotation.Nullable;
25 import java.io.Serializable;
26 import java.util.*;
27 import java.util.stream.Collectors;
28
29
30
31
32
33
34 class GenericAnovaResultImpl implements Serializable, GenericAnovaResult {
35
36 private static final long serialVersionUID = 1L;
37
38 private final String key;
39 private final Map<TreeSet<String>, AnovaEffect> interactionEffects = new LinkedHashMap<>();
40 private final Map<String, AnovaEffect> mainEffects = new LinkedHashMap<>();
41 @Nullable
42 private final AnovaEffect residual;
43
44 public GenericAnovaResultImpl( String key, Collection<AnovaEffect> effects ) {
45 this.key = key;
46 AnovaEffect residual = null;
47 for ( AnovaEffect ae : effects ) {
48 String termLabel = ae.getEffectName();
49 if ( ae.isInteraction() ) {
50 interactionEffects.put( new TreeSet<>( Arrays.asList( StringUtils.split( termLabel, ":" ) ) ), ae );
51 } else if ( ae.isResiduals() ) {
52 residual = ae;
53 } else {
54 mainEffects.put( termLabel, ae );
55 }
56 }
57 this.residual = residual;
58 }
59
60 @Override
61 public String getKey() {
62 return key;
63 }
64
65 @Override
66 public boolean hasResiduals() {
67 return residual != null;
68 }
69
70 @Override
71 public double getResidualsDof() {
72 return residual != null ? residual.getDof() : Double.NaN;
73 }
74
75 @Override
76 public double getResidualsFStat() {
77 return residual != null ? residual.getFStat() : Double.NaN;
78 }
79
80 @Override
81 public double getResidualsPValue() {
82 return residual != null ? residual.getPValue() : Double.NaN;
83 }
84
85 @Override
86 public double getInteractionEffectDof() {
87 if ( interactionEffects.size() > 1 ) {
88 throw new IllegalStateException( "Must specify which interaction" );
89 }
90 if ( interactionEffects.isEmpty() ) {
91 return Double.NaN;
92 }
93 return interactionEffects.values().iterator().next().getDof();
94 }
95
96 @Override
97 public double getInteractionEffectFStat() {
98 if ( interactionEffects.size() > 1 ) {
99 throw new IllegalStateException( "Must specify which interaction" );
100 }
101 if ( interactionEffects.isEmpty() ) {
102 return Double.NaN;
103 }
104 return interactionEffects.values().iterator().next().getFStat();
105 }
106
107 @Override
108 public double getInteractionEffectPValue() {
109 if ( interactionEffects.size() > 1 ) {
110 throw new IllegalStateException( "Must specify which interaction" );
111 }
112 if ( interactionEffects.isEmpty() ) {
113 return Double.NaN;
114 }
115 return interactionEffects.values().iterator().next().getPValue();
116 }
117
118 @Override
119 public Collection<String[]> getInteractionEffectFactorNames() {
120 return interactionEffects.keySet().stream()
121 .map( fn -> fn.toArray( new String[0] ) )
122 .collect( Collectors.toList() );
123 }
124
125 @Override
126 public double getInteractionEffectDof( String... factorNames ) {
127 if ( interactionEffects.isEmpty() ) {
128 return Double.NaN;
129 }
130 Set<String> interactionFactor = new TreeSet<>( Arrays.asList( factorNames ) );
131 if ( !interactionEffects.containsKey( interactionFactor ) ) {
132 return Double.NaN;
133 }
134 return interactionEffects.get( interactionFactor ).getDof();
135 }
136
137 @Override
138 public double getInteractionEffectFStat( String... factorNames ) {
139 if ( interactionEffects.isEmpty() ) {
140 return Double.NaN;
141 }
142 TreeSet<String> interactionFactor = new TreeSet<>( Arrays.asList( factorNames ) );
143 if ( !interactionEffects.containsKey( interactionFactor ) ) {
144 return Double.NaN;
145 }
146 return interactionEffects.get( interactionFactor ).getFStat();
147 }
148
149 @Override
150 public double getInteractionEffectPValue( String... factorNames ) {
151 if ( interactionEffects.isEmpty() ) {
152 return Double.NaN;
153 }
154 TreeSet<String> interactionFactor = new TreeSet<>( Arrays.asList( factorNames ) );
155 if ( !interactionEffects.containsKey( interactionFactor ) ) {
156 return Double.NaN;
157 }
158 return interactionEffects.get( interactionFactor ).getPValue();
159 }
160
161 @Override
162 public double getMainEffectDof( String factorName ) {
163 if ( mainEffects.get( factorName ) == null ) {
164 return Double.NaN;
165 }
166 return mainEffects.get( factorName ).getDof();
167 }
168
169 @Override
170 public double getMainEffectFStat( String factorName ) {
171 if ( mainEffects.get( factorName ) == null ) {
172 return Double.NaN;
173 }
174 return mainEffects.get( factorName ).getFStat();
175 }
176
177
178
179
180 @Override
181 public Collection<String> getMainEffectFactorNames() {
182 return mainEffects.keySet();
183 }
184
185 @Override
186 public double getMainEffectPValue( String factorName ) {
187 if ( mainEffects.get( factorName ) == null ) {
188 return Double.NaN;
189 }
190 return mainEffects.get( factorName ).getPValue();
191 }
192
193 @Override
194 public boolean hasInteractions() {
195 return !interactionEffects.isEmpty();
196 }
197
198 @Override
199 public int hashCode() {
200 final int prime = 31;
201 int result = 1;
202 result = prime * result + ( ( key == null ) ? 0 : key.hashCode() );
203 return result;
204 }
205
206 @Override
207 public boolean equals( Object obj ) {
208 if ( this == obj ) return true;
209 if ( obj == null ) return false;
210 if ( getClass() != obj.getClass() ) return false;
211 GenericAnovaResultImpl/basecode/math/linearmodels/GenericAnovaResultImpl.html#GenericAnovaResultImpl">GenericAnovaResultImpl other = ( GenericAnovaResultImpl ) obj;
212 if ( key == null ) {
213 if ( other.key != null ) return false;
214 } else if ( !key.equals( other.key ) ) return false;
215 return true;
216 }
217
218 @Override
219 public String toString() {
220 StringBuilder buf = new StringBuilder();
221
222 buf.append( "ANOVA table " ).append( this.getKey() ).append( " \n" );
223
224 buf.append( StringUtils.leftPad( "\t", 10 ) ).append( "Df\tSSq\tMSq\tF\tP\n" );
225
226 for ( String me : this.getMainEffectFactorNames() ) {
227 if ( me.equals( LinearModelSummary.INTERCEPT_COEFFICIENT_NAME ) ) {
228 continue;
229 }
230 AnovaEffect a = mainEffects.get( me );
231 buf.append( a ).append( "\n" );
232 }
233
234 if ( hasInteractions() ) {
235 for ( TreeSet<String> ifa : interactionEffects.keySet() ) {
236 AnovaEffect a = this.interactionEffects.get( ifa );
237 buf.append( a ).append( "\n" );
238 }
239 }
240
241 buf.append( residual ).append( "\n" );
242
243 return buf.toString();
244 }
245 }