package gov.nih.ncgc.bard.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import gov.nih.ncgc.bard.rest.BARDConstants;
import gov.nih.ncgc.bard.rest.rowdef.AssayDefinitionObject;
import gov.nih.ncgc.bard.rest.rowdef.DataResultObject;
import gov.nih.ncgc.bard.rest.rowdef.DoseResponseResultObject;
import gov.nih.ncgc.bard.tools.BARDJsonRequired;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A representation of experiment data (ie measurements).
*
* @author Rajarshi Guha
*/
public class ExperimentData extends BaseEntity {
@BARDJsonRequired
String exptDataId;
Long cid, sid;
Long bardExptId, bardAssayId;
Long capExptId, capAssayId;
List<Long> capProjId, bardProjId;
String resultJson;
@JsonIgnore
Date updated;
String runset = "default";
int outcome, score;
Integer classification;
Float potency;
List<FitModel> readouts;
/**
* Reperesents the context of <code>bard_experiment_data.json_data_array</code>.
*/
@JsonIgnore
DataResultObject[] results;
/**
* Reperesents the context of <code>bard_experiment_data.json_dose_response</code>.
*/
@JsonIgnore
DoseResponseResultObject[] dr = null;
@JsonIgnore
AssayDefinitionObject[] ado;
public ExperimentData() {
}
public List<Long> getBardProjId() {
return bardProjId;
}
public void setBardProjId(List<Long> bardProjId) {
this.bardProjId = bardProjId;
}
public List<Long> getCapProjId() {
return capProjId;
}
public void setCapProjId(List<Long> capProjId) {
this.capProjId = capProjId;
}
public Long getBardAssayId() {
return bardAssayId;
}
public void setBardAssayId(Long bardAssayId) {
this.bardAssayId = bardAssayId;
}
public Long getCapExptId() {
return capExptId;
}
public void setCapExptId(Long capExptId) {
this.capExptId = capExptId;
}
public Long getCapAssayId() {
return capAssayId;
}
public void setCapAssayId(Long capAssayId) {
this.capAssayId = capAssayId;
}
public String getResultJson() {
return resultJson;
}
public void setResultJson(String resultJson) {
this.resultJson = resultJson;
}
/**
* Convert the internal representation to a custom form, suitable for JSON output.
*/
public void transform() {
readouts = new ArrayList<FitModel>();
if (dr != null) { // we have one or CRC layers
for (DoseResponseResultObject dro : dr) {
FitModel model = new FitModel("dose response", dro.getZeroAct(), dro.getInfAct(), dro.getHillCoef(), dro.getAc50());
Double[][] cr = new Double[dro.getDose().length][2];
for (int i = 0; i < dro.getDose().length; i++) {
cr[i][0] = dro.getDose()[i];
cr[i][1] = dro.getResponse()[i];
}
model.setCr(cr);
model.setName(dro.getLabel());
model.setDescription(dro.getDescription());
//model.setConcUnit(dro.getConcUnit());
model.setConcUnit("M"); // force Molar
if (model.unfitted()) {
model.setS0(null);
model.setAc50(null);
model.setsInf(null);
model.setHill(null);
}
readouts.add(model);
}
} else {
// probably a single point
for (DataResultObject o : results) {
// we're going to force all non-PubChem TID's into individual readouts.
// ideally we should recognize relevant readouts, but that's not happening soon
if (o.getTid() == -1) continue;
FitModel model = new FitModel();
model.setDescription("single point");
model.setName(o.getResultName());
Double[][] cr = new Double[1][2];
cr[0][0] = null;
cr[0][1] = null;
String val = (String) o.getValue();
Double dval = null;
try {
if (val != null) {
cr[0][1] = Double.parseDouble(val);
String[] concAndUnit = getConcAndUnitsFromTitle(o.getResultName());
if (concAndUnit[0] != null) {
cr[0][0] = Double.parseDouble(concAndUnit[0]);
model.setConcUnit(concAndUnit[1]);
} else { // try pulling it from the result type definition
for (AssayDefinitionObject ao : ado) {
if (o.getTid() == Integer.parseInt(ao.getTid())) {
if (ao.getTestConcUnit() != null && !ao.getTestConcUnit().equals("none"))
model.setConcUnit(ao.getTestConcUnit());
if (ao.getTestConcentration() != null && ao.getTestConcentration().length > 0) {
cr[0][0] = (double) ao.getTestConcentration()[0];
}
}
}
}
}
} catch (NumberFormatException e) {
}
model.setCr(cr);
readouts.add(model);
}
}
}
String[] getConcAndUnitsFromTitle(String title) {
String conc = null, unit = null;
Pattern uM = Pattern.compile("(\\d+\\.?\\d+?\\s?)uM");
Pattern nM = Pattern.compile("(\\d+\\.?\\d+?\\s?)nM");
Pattern M = Pattern.compile("(\\d+\\.?\\d+?\\s?)M");
Matcher matcher = uM.matcher(title);
if (matcher.find()) {
conc = matcher.group(1);
unit = "uM";
}
if (conc == null) {
matcher = nM.matcher(title);
if (matcher.find()) {
conc = matcher.group(1);
unit = "nM";
}
}
if (conc == null) {
matcher = M.matcher(title);
if (matcher.find()) {
conc = matcher.group(1);
unit = "M";
}
}
return new String[]{conc, unit};
}
public DoseResponseResultObject[] getDr() {
return dr;
}
public void setDr(DoseResponseResultObject[] dr) {
this.dr = dr;
}
public List<FitModel> getReadouts() {
return readouts;
}
public void setReadouts(List<FitModel> readouts) {
this.readouts = readouts;
}
/**
* Reperesents the context of <code>bard_experiment_data.json_data_array</code>.
*
* @return
*/
public DataResultObject[] getResults() {
return results;
}
public void setResults(DataResultObject[] results) {
this.results = results;
}
@JsonIgnore
public AssayDefinitionObject[] getDefs() {
return ado;
}
@JsonIgnore
public void setDefs(AssayDefinitionObject[] ado) {
this.ado = ado;
}
public int getOutcome() {
return outcome;
}
public void setOutcome(int outcome) {
this.outcome = outcome;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public Float getPotency() {
return potency;
}
public void setPotency(Float potency) {
this.potency = potency;
}
public String getExptDataId() {
return exptDataId;
}
public void setExptDataId(String exptDataId) {
this.exptDataId = exptDataId;
if (exptDataId != null && exptDataId.contains(".")) {
String[] toks = exptDataId.split("\\.");
if (toks.length == 2) {
bardExptId = Long.parseLong(toks[0]);
sid = Long.parseLong(toks[1]);
}
}
}
public Long getBardExptId() {
return bardExptId;
}
public void setBardExptId(Long bardExptId) {
this.bardExptId = bardExptId;
}
public Long getCid() {
return cid;
}
public void setCid(Long cid) {
this.cid = cid;
}
public Long getSid() {
return sid;
}
public void setSid(Long sid) {
this.sid = sid;
}
public Integer getClassification() {
return classification;
}
public void setClassification(Integer classification) {
this.classification = classification;
}
public Date getUpdated() {
return updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
public String getRunset() {
return runset;
}
public void setRunset(String runset) {
this.runset = runset;
}
public String toString() {
return "ExperimentData[" + exptDataId + ", outcome=" + outcome + ", score=" + score + ", potency=" + potency + "]";
}
/**
* Return the path for this resource in the REST API.
* <p/>
* The actual resource can be accessed by prepending the hostname of the server
* hosting the REST API.
*
* @return The path to this resource. <code>null</code> if the object is not meant
* to be publically available via the REST API
*/
public String getResourcePath() {
return BARDConstants.API_BASE + "/exptdata/" + bardExptId + "." + sid;
}
/**
* Set the resource path.
* <p/>
* In most cases, this can be an empty function as its primary purpose
* is to allow Jackson to deserialize a JSON entity to the relevant Java
* entity.
*
* @param resourcePath the resource path for this entity
*/
public void setResourcePath(String resourcePath) {
//To change body of implemented methods use File | Settings | File Templates.
}
}