package gov.nih.ncgc.bard.capextract.resultextract;
import java.util.ArrayList;
import java.util.Vector;
import java.util.logging.Logger;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
/**
* This class encapsulated concentration response data and it annotated to include specific fields in when converted to JSON.
* THe standard output fields include concentration response points and fit parameters.
*
* @author braistedjc
*
*/
public class BardConcResponseSeries {
@JsonIgnore
Logger logger = Logger.getLogger(BardConcResponseSeries.class.getName());
@JsonInclude(Include.NON_NULL)
private String responseUnit;
@JsonInclude(Include.NON_NULL)
private String testConcUnit;
@JsonInclude(Include.NON_NULL)
private Integer crSeriesDictId;
@JsonIgnore
private BardResultType parentElement;
@JsonIgnore
private ArrayList <BardResultType> parameterList;
@JsonInclude(Include.NON_NULL)
private String readoutName;
@JsonInclude(Include.NON_NULL)
private HillParameters concRespParams;
private ArrayList <BardResultType> concRespPoints;
@JsonIgnore
private BardResultType [] persistConcRespPointArr;
@JsonInclude(Include.NON_NULL)
private ArrayList <BardResultType> miscData;
/**
* Default Constructor
*/
public BardConcResponseSeries() {
concRespParams = new HillParameters();
parameterList = new ArrayList <BardResultType>();
concRespPoints = new ArrayList <BardResultType>();
miscData = new ArrayList <BardResultType>();
}
/**
* Makes an internal copy of all C/R points
* @return
*/
public ArrayList <BardResultType> cloneConcRespPoints() {
ArrayList <BardResultType> newConcRespList = new ArrayList <BardResultType>();
for(BardResultType point : concRespPoints)
newConcRespList.add(point);
return newConcRespList;
}
/**
* Looks for hill parameters among child data elements and builds the HillParameter class.
*
* @param logXx50ParameterV List of log AC50-like measures (dictionary IDs)
* @param xx50ParameterV List of AC50-like measures, dictionary ids
* @throws Exception
*/
public void reconcileParameters(Vector <Integer> logXx50ParameterV, Vector <Integer> xx50ParameterV) throws Exception {
concRespParams = new HillParameters();
Double value;
String valueStr;
if(parameterList.size() > 4) {
logger.warning("Potential Problem: parameterList (Hill Params) is too large, #params="+parameterList.size());
for(BardResultType p : parameterList) {
System.out.println(p.getDictElemId()+" "+p.getDisplayName());
}
}
for(BardResultType param : parameterList) {
valueStr = param.getValue();
if(valueStr == null || valueStr.trim().isEmpty())
value = null;
else
value = Double.parseDouble(valueStr);
if(param.getDictElemId() == 920) {
concRespParams.setS0(value);
} else if(param.getDictElemId() == 921) {
concRespParams.setsInf(value);
} else if(param.getDictElemId() == 919) {
concRespParams.setHillCoef(value);
} else if(logXx50ParameterV.contains(param.getDictElemId())) {
concRespParams.setLogEc50(value);
}
}
//if ec50 is the parent node, then set the hill parameter by taking log(ec50)
if(parentElement.getValue() != null && concRespParams.getLogEc50() == null && xx50ParameterV.contains(parentElement.getDictElemId())) {
Double logEc50;
try {
logEc50 = Double.parseDouble(parentElement.getValue());
//xx50 values are in uM, logEc50 is typically in molar (mol/L) units
//multiplying by 10^-6 prior to log to change the convention.
if(logEc50 > 0d)
logEc50 = Math.log10(logEc50 * Math.pow(10, -6.0));
else
logEc50 = null;
} catch (NumberFormatException nfe) {
logEc50 = null;
}
concRespParams.setLogEc50(logEc50);
}
}
/**
* Initializes for display but setting extraneous fields to null.
*/
public void initializeForDisplay() {
String testUnit = null;
String respUnit = null;
Integer pointDictId = null;
String readout = null;
int ptCnt = 0;
ArrayList <BardResultType> nullCRPoints = new ArrayList <BardResultType>();
persistConcRespPointArr = new BardResultType[concRespPoints.size()];
for(BardResultType result : concRespPoints) {
if(ptCnt < 1) {
testUnit = result.getTestConcUnit();
respUnit = (result.getResponseUnit() != null) ? result.getResponseUnit() : result.getDisplayName();
pointDictId = result.getDictElemId();
readout = result.getReadoutName();
}
result.setDisplayName(null);
result.setTestConcUnit(null);
result.setResponseUnit(null);
result.setDictElemId(null);
result.setReadoutName(null);
result.setQualifierValue(null);
if(result.getValue() == null || result.getValue().equals("NA"))
nullCRPoints.add(result);
//add each cr point to the array
persistConcRespPointArr[ptCnt] = result;
ptCnt++;
}
concRespPoints.removeAll(nullCRPoints);
this.responseUnit = respUnit;
this.testConcUnit = testUnit;
this.crSeriesDictId = pointDictId;
this.readoutName = readout;
if(miscData != null && miscData.size() == 0)
miscData = null;
if(concRespParams != null && concRespParams.areAllParametersNull())
concRespParams = null;
}
/**
* This method collapses data to minimize payload for rendering C/R series
*/
public void prepareForDisplay() {
//need to resptore possibly mising cr points
concRespPoints.clear();
for(BardResultType crPoint : persistConcRespPointArr) {
concRespPoints.add(crPoint);
}
ArrayList <BardResultType> nullCRPoints = new ArrayList <BardResultType>();
if(concRespParams != null && concRespParams.areAllParametersNull())
concRespParams = null;
if(concRespPoints != null) {
for(BardResultType result : concRespPoints) {
if(result.getValue() == null || result.getValue().equals("NA"))
nullCRPoints.add(result);
}
}
concRespPoints.removeAll(nullCRPoints);
}
public ArrayList<BardResultType> getConcRespPoints() {
return concRespPoints;
}
public void setConcRespPoints(ArrayList<BardResultType> concRespPoints) {
this.concRespPoints = concRespPoints;
}
public ArrayList<BardResultType> getMiscData() {
return miscData;
}
public void setMiscData(ArrayList<BardResultType> miscData) {
this.miscData = miscData;
}
public String getResponseUnit() {
return responseUnit;
}
public void setResponseUnit(String responseUnit) {
this.responseUnit = responseUnit;
}
public String getTestConcUnit() {
return testConcUnit;
}
public void setTestConcUnit(String testConcUnit) {
this.testConcUnit = testConcUnit;
}
public Integer getCrSeriesDictId() {
return crSeriesDictId;
}
public void setCrSeriesDictId(Integer crSeriesDictId) {
this.crSeriesDictId = crSeriesDictId;
}
public BardResultType getParentElement() {
return parentElement;
}
public void setParentElement(BardResultType parentNode) {
this.parentElement = parentNode;
}
public ArrayList<BardResultType> getParameterList() {
return parameterList;
}
public void setParameterList(ArrayList<BardResultType> parameterList) {
this.parameterList = parameterList;
}
public HillParameters getConcRespParams() {
return concRespParams;
}
public void setConcRespParams(HillParameters concRespParams) {
this.concRespParams = concRespParams;
}
/**
* Hill Parameter Class
* @author braistedjc
*
*/
private class HillParameters {
private Double s0;
private Double sInf;
private Double hillCoef;
private Double logEc50;
public HillParameters() { }
public boolean areAllParametersNull() {
return (s0 == null && sInf == null && hillCoef == null && logEc50 == null);
}
public Double getS0() {
return s0;
}
public void setS0(Double s0) {
this.s0 = s0;
}
public Double getsInf() {
return sInf;
}
public void setsInf(Double sInf) {
this.sInf = sInf;
}
public Double getHillCoef() {
return hillCoef;
}
public void setHillCoef(Double hillCoef) {
this.hillCoef = hillCoef;
}
public Double getLogEc50() {
return logEc50;
}
public void setLogEc50(Double logEc50) {
this.logEc50 = logEc50;
}
}
}