32
32
import org .slf4j .LoggerFactory ;
33
33
import org .springframework .stereotype .Service ;
34
34
35
- import com .fasterxml .jackson .annotation .JsonCreator ;
36
- import com .fasterxml .jackson .annotation .JsonProperty ;
37
35
import com .fasterxml .jackson .core .JsonProcessingException ;
38
36
import com .fasterxml .jackson .databind .ObjectMapper ;
39
37
40
38
import eu .openanalytics .phaedra .calculationservice .exception .CalculationException ;
41
39
import eu .openanalytics .phaedra .calculationservice .execution .CalculationContext ;
40
+ import eu .openanalytics .phaedra .calculationservice .execution .input .CalculationInputHelper ;
42
41
import eu .openanalytics .phaedra .calculationservice .execution .progress .CalculationStage ;
43
42
import eu .openanalytics .phaedra .calculationservice .execution .progress .CalculationStateEventCode ;
44
43
import eu .openanalytics .phaedra .calculationservice .execution .script .ScriptExecutionRequest ;
60
59
* but also stats for each welltype present in the plate.
61
60
*
62
61
* Feature Stats can be calculated as soon as the Feature itself has been calculated.
62
+ *
63
+ * TODO: wellType is still named "welltype" in protocol-service and resultdata-service. Fix naming across all services
63
64
*/
64
65
@ Service
65
66
public class FeatureStatExecutorService {
@@ -133,31 +134,36 @@ private FeatureStatDTO findStat(CalculationContext ctx, long featureId, long sta
133
134
134
135
private Map <String , Object > collectStatInputData (CalculationContext ctx , FeatureDTO feature , FeatureStatDTO featureStat ) {
135
136
Map <String , Object > input = new HashMap <String , Object >();
136
- input .put ("lowWelltype" , ctx .getProtocolData ().protocol .getLowWelltype ());
137
- input .put ("highWelltype" , ctx .getProtocolData ().protocol .getHighWelltype ());
138
- input .put ("welltypes" , ctx .getWells ().stream ().map (WellDTO ::getWellType ).toList ());
137
+ CalculationInputHelper .addWellInfo (input , ctx , ctx .getWells ());
138
+ // Note: assuming here that the feature values are already sorted by well nr
139
139
input .put ("featureValues" , ctx .getFeatureResults ().get (feature .getId ()).getValues ());
140
140
input .put ("isPlateStat" , featureStat .getPlateStat ());
141
- input .put ("isWelltypeStat " , featureStat .getWelltypeStat ());
141
+ input .put ("isWellTypeStat " , featureStat .getWelltypeStat ());
142
142
return input ;
143
143
}
144
144
145
- private List <ResultFeatureStatDTO > parseResults (CalculationContext ctx , FeatureDTO feature , FeatureStatDTO featureStat , ScriptExecutionOutputDTO output ) {
145
+ private List <ResultFeatureStatDTO > parseResults (CalculationContext ctx , FeatureDTO feature , FeatureStatDTO featureStat , ScriptExecutionOutputDTO output ) {
146
146
List <ResultFeatureStatDTO > results = new ArrayList <>();
147
147
148
148
float plateValue = Float .NaN ;
149
- Map <String , Float > wellTypeValues = null ;
149
+ Map <String , Float > wellTypeValues = new HashMap <>();
150
+
150
151
try {
151
- OutputWrapper outputWrapper = objectMapper .readValue (output .getOutput (), OutputWrapper .class );
152
- plateValue = outputWrapper .getPlateValue ().orElse (Float .NaN );
153
- wellTypeValues = outputWrapper .getWelltypeOutputs ();
152
+ Map <?,?> outputMap = objectMapper .readValue (output .getOutput (), Map .class );
153
+ outputMap = (Map <?,?>) outputMap .get ("output" ); // Output string contains a nested 'output' key, e.g. output = "{\"output\":{\"plateValue\":384,\"wellTypeValues\":{\"HC\":32,\"LC\":32,\"SAMPLE\":320}}}\n"
154
+ if (outputMap .get ("plateValue" ) instanceof Number ) plateValue = ((Number ) outputMap .get ("plateValue" )).floatValue ();
155
+ if (outputMap .get ("wellTypeValues" ) instanceof Map ) {
156
+ Map <?,?> wellTypeValuesMap = (Map <?,?>) outputMap .get ("wellTypeValues" );
157
+ wellTypeValuesMap .entrySet ().stream ().filter (e -> e .getValue () instanceof Number ).forEach (e -> wellTypeValues .put ((String ) e .getKey (), ((Number ) e .getValue ()).floatValue ()));
158
+ }
154
159
} catch (JsonProcessingException e ) {
155
160
throw new CalculationException ("Invalid response JSON" , e );
156
161
}
157
162
158
163
if (featureStat .getPlateStat ()) {
159
164
results .add (createResultStatDTO (feature , featureStat , output , plateValue , null ));
160
165
}
166
+
161
167
if (featureStat .getWelltypeStat ()) {
162
168
List <String > wellTypes = ctx .getWells ().stream ().map (WellDTO ::getWellType ).distinct ().toList ();
163
169
for (String wellType : wellTypes ) {
@@ -181,29 +187,4 @@ private ResultFeatureStatDTO createResultStatDTO(FeatureDTO feature, FeatureStat
181
187
.exitCode (output .getExitCode ())
182
188
.build ();
183
189
}
184
-
185
- private static class OutputWrapper {
186
-
187
- private final Float plateValue ;
188
- private final Map <String , Float > welltypeValues ;
189
-
190
- @ JsonCreator
191
- private OutputWrapper (
192
- @ JsonProperty (value = "plateValue" , required = true ) Float plateValue ,
193
- @ JsonProperty (value = "welltypeValues" , required = true ) Map <String , Float > welltypeValues ) {
194
- this .plateValue = plateValue ;
195
- this .welltypeValues = welltypeValues ;
196
- }
197
-
198
- public Optional <Float > getPlateValue () {
199
- return Optional .ofNullable (plateValue );
200
- }
201
-
202
-
203
- public Map <String , Float > getWelltypeOutputs () {
204
- return welltypeValues ;
205
- }
206
-
207
- }
208
-
209
190
}
0 commit comments