package uk.ac.ox.zoo.seeg.abraid.mp.common.domain;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import uk.ac.ox.zoo.seeg.abraid.mp.common.dto.csv.CsvSubmodelStatistic;
import uk.ac.ox.zoo.seeg.abraid.mp.common.dto.json.JsonModelRunStatistics;
import javax.persistence.*;
import java.util.List;
import static ch.lambdaj.Lambda.*;
import static org.hamcrest.core.IsNull.notNullValue;
/**
* Represents the validation statistics for a submodel in a model run.
* Copyright (c) 2014 University of Oxford
*/
@Entity
@Table(name = "submodel_statistic")
@NamedQueries({
@NamedQuery(
name = "getSubmodelStatisticsForModelRun",
query = "from SubmodelStatistic where modelRun=:modelRun"
)
})
public class SubmodelStatistic {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne
@JoinColumn(name = "model_run_id", nullable = false)
private ModelRun modelRun;
// "kappa"
private Double kappa;
// "auc"
@Column(name = "area_under_curve")
private Double areaUnderCurve;
// "sens"
private Double sensitivity;
// "spec"
private Double specificity;
// "pcc"
@Column(name = "proportion_correctly_classified")
private Double proportionCorrectlyClassified;
// "kappa_sd"
@Column(name = "kappa_sd")
private Double kappaStandardDeviation;
// "auc_sd"
@Column(name = "area_under_curve_sd")
private Double areaUnderCurveStandardDeviation;
// "sens_sd"
@Column(name = "sensitivity_sd")
private Double sensitivityStandardDeviation;
// "spec_sd"
@Column(name = "specificity_sd")
private Double specificityStandardDeviation;
// "pcc_sd"
@Column(name = "proportion_correctly_classified_sd")
private Double proportionCorrectlyClassifiedStandardDeviation;
public SubmodelStatistic() {
}
public SubmodelStatistic(Double kappa, Double areaUnderCurve,
Double sensitivity, Double specificity, Double proportionCorrectlyClassified) {
setKappa(kappa);
setAreaUnderCurve(areaUnderCurve);
setSensitivity(sensitivity);
setSpecificity(specificity);
setProportionCorrectlyClassified(proportionCorrectlyClassified);
}
public SubmodelStatistic(CsvSubmodelStatistic dto, ModelRun parentRun) {
setModelRun(parentRun);
setKappa(dto.getKappa());
setAreaUnderCurve(dto.getAreaUnderCurve());
setSensitivity(dto.getSensitivity());
setSpecificity(dto.getSpecificity());
setProportionCorrectlyClassified(dto.getProportionCorrectlyClassified());
setKappaStandardDeviation(dto.getKappaStandardDeviation());
setAreaUnderCurveStandardDeviation(dto.getAreaUnderCurveStandardDeviation());
setSensitivityStandardDeviation(dto.getSensitivityStandardDeviation());
setSpecificityStandardDeviation(dto.getSpecificityStandardDeviation());
setProportionCorrectlyClassifiedStandardDeviation(dto.getProportionCorrectlyClassifiedStandardDeviation());
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public ModelRun getModelRun() {
return modelRun;
}
public void setModelRun(ModelRun modelRun) {
this.modelRun = modelRun;
}
public Double getKappa() {
return kappa;
}
public void setKappa(Double kappa) {
this.kappa = kappa;
}
public Double getAreaUnderCurve() {
return areaUnderCurve;
}
public void setAreaUnderCurve(Double areaUnderCurve) {
this.areaUnderCurve = areaUnderCurve;
}
public Double getSensitivity() {
return sensitivity;
}
public void setSensitivity(Double sensitivity) {
this.sensitivity = sensitivity;
}
public Double getSpecificity() {
return specificity;
}
public void setSpecificity(Double specificity) {
this.specificity = specificity;
}
public Double getProportionCorrectlyClassified() {
return proportionCorrectlyClassified;
}
public void setProportionCorrectlyClassified(Double proportionCorrectlyClassified) {
this.proportionCorrectlyClassified = proportionCorrectlyClassified;
}
public Double getKappaStandardDeviation() {
return kappaStandardDeviation;
}
public void setKappaStandardDeviation(Double kappaStandardDeviation) {
this.kappaStandardDeviation = kappaStandardDeviation;
}
public Double getAreaUnderCurveStandardDeviation() {
return areaUnderCurveStandardDeviation;
}
public void setAreaUnderCurveStandardDeviation(Double areaUnderCurveStandardDeviation) {
this.areaUnderCurveStandardDeviation = areaUnderCurveStandardDeviation;
}
public Double getSensitivityStandardDeviation() {
return sensitivityStandardDeviation;
}
public void setSensitivityStandardDeviation(Double sensitivityStandardDeviation) {
this.sensitivityStandardDeviation = sensitivityStandardDeviation;
}
public Double getSpecificityStandardDeviation() {
return specificityStandardDeviation;
}
public void setSpecificityStandardDeviation(Double specificityStandardDeviation) {
this.specificityStandardDeviation = specificityStandardDeviation;
}
public Double getProportionCorrectlyClassifiedStandardDeviation() {
return proportionCorrectlyClassifiedStandardDeviation;
}
public void setProportionCorrectlyClassifiedStandardDeviation(
Double proportionCorrectlyClassifiedStandardDeviation) {
this.proportionCorrectlyClassifiedStandardDeviation = proportionCorrectlyClassifiedStandardDeviation;
}
///COVERAGE:OFF - generated code
///CHECKSTYLE:OFF AvoidInlineConditionalsCheck|LineLengthCheck|MagicNumberCheck|NeedBracesCheck - generated code
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SubmodelStatistic that = (SubmodelStatistic) o;
if (areaUnderCurve != null ? !areaUnderCurve.equals(that.areaUnderCurve) : that.areaUnderCurve != null)
return false;
if (areaUnderCurveStandardDeviation != null ? !areaUnderCurveStandardDeviation.equals(that.areaUnderCurveStandardDeviation) : that.areaUnderCurveStandardDeviation != null)
return false;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
if (kappa != null ? !kappa.equals(that.kappa) : that.kappa != null) return false;
if (kappaStandardDeviation != null ? !kappaStandardDeviation.equals(that.kappaStandardDeviation) : that.kappaStandardDeviation != null)
return false;
if (modelRun != null ? !modelRun.equals(that.modelRun) : that.modelRun != null) return false;
if (proportionCorrectlyClassified != null ? !proportionCorrectlyClassified.equals(that.proportionCorrectlyClassified) : that.proportionCorrectlyClassified != null)
return false;
if (proportionCorrectlyClassifiedStandardDeviation != null ? !proportionCorrectlyClassifiedStandardDeviation.equals(that.proportionCorrectlyClassifiedStandardDeviation) : that.proportionCorrectlyClassifiedStandardDeviation != null)
return false;
if (sensitivity != null ? !sensitivity.equals(that.sensitivity) : that.sensitivity != null) return false;
if (sensitivityStandardDeviation != null ? !sensitivityStandardDeviation.equals(that.sensitivityStandardDeviation) : that.sensitivityStandardDeviation != null)
return false;
if (specificity != null ? !specificity.equals(that.specificity) : that.specificity != null) return false;
if (specificityStandardDeviation != null ? !specificityStandardDeviation.equals(that.specificityStandardDeviation) : that.specificityStandardDeviation != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (modelRun != null ? modelRun.hashCode() : 0);
result = 31 * result + (kappa != null ? kappa.hashCode() : 0);
result = 31 * result + (areaUnderCurve != null ? areaUnderCurve.hashCode() : 0);
result = 31 * result + (sensitivity != null ? sensitivity.hashCode() : 0);
result = 31 * result + (specificity != null ? specificity.hashCode() : 0);
result = 31 * result + (proportionCorrectlyClassified != null ? proportionCorrectlyClassified.hashCode() : 0);
result = 31 * result + (kappaStandardDeviation != null ? kappaStandardDeviation.hashCode() : 0);
result = 31 * result + (areaUnderCurveStandardDeviation != null ? areaUnderCurveStandardDeviation.hashCode() : 0);
result = 31 * result + (sensitivityStandardDeviation != null ? sensitivityStandardDeviation.hashCode() : 0);
result = 31 * result + (specificityStandardDeviation != null ? specificityStandardDeviation.hashCode() : 0);
result = 31 * result + (proportionCorrectlyClassifiedStandardDeviation != null ? proportionCorrectlyClassifiedStandardDeviation.hashCode() : 0);
return result;
}
///CHECKSTYLE:ON
///COVERAGE:ON
/**
* Gets the set of summarising statistics across all submodels of a model run.
* @param submodelStatistics The list of submodel statistics.
* @return The DTO representing the set of summarising statistics.
*/
public static JsonModelRunStatistics summarise(List<SubmodelStatistic> submodelStatistics) {
JsonModelRunStatistics json = new JsonModelRunStatistics();
List<SubmodelStatistic> completeSubmodels = filter(
having(on(SubmodelStatistic.class).containsAllRequiredPropertiesForSummarising()),
filter(notNullValue(), submodelStatistics));
if (!completeSubmodels.isEmpty()) {
DescriptiveStatistics kappaStats = new DescriptiveStatistics();
DescriptiveStatistics aucStats = new DescriptiveStatistics();
DescriptiveStatistics sensStats = new DescriptiveStatistics();
DescriptiveStatistics specStats = new DescriptiveStatistics();
DescriptiveStatistics pccStats = new DescriptiveStatistics();
for (SubmodelStatistic submodelStatistic : completeSubmodels) {
kappaStats.addValue(submodelStatistic.getKappa());
aucStats.addValue(submodelStatistic.getAreaUnderCurve());
sensStats.addValue(submodelStatistic.getSensitivity());
specStats.addValue(submodelStatistic.getSpecificity());
pccStats.addValue(submodelStatistic.getProportionCorrectlyClassified());
}
json.setKappa(kappaStats.getMean());
json.setKappaSd(kappaStats.getStandardDeviation());
json.setAuc(aucStats.getMean());
json.setAucSd(aucStats.getStandardDeviation());
json.setSens(sensStats.getMean());
json.setSensSd(sensStats.getStandardDeviation());
json.setSpec(specStats.getMean());
json.setSpecSd(specStats.getStandardDeviation());
json.setPcc(pccStats.getMean());
json.setPccSd(pccStats.getStandardDeviation());
}
return json;
}
/**
* Checks that the submodel statistic contains a value for each of the main fields (excludes standard deviations).
* @return true if all required fields present, otherwise false.
*/
protected boolean containsAllRequiredPropertiesForSummarising() {
return
kappa != null &&
areaUnderCurve != null &&
sensitivity != null &&
specificity != null &&
proportionCorrectlyClassified != null;
}
}