package org.cellocad.MIT.dnacompiler;
/**
* Created by Bryan Der on 3/26/14.
*/
import java.util.ArrayList;
import java.util.Collections;
/**
* Gate Toxicity: 1=nontoxic growth, 0=no growth. Circuit Toxicity is multiplicative for all gates.
*
* Toxicity data for a repressor takes the form of an array of OD measurements, where each OD measurement
* corresponds to an input RPU level. Toxicity evaluation is performed by a weighted average of the nearest OD datapoints
* given the incoming RPU.
*
* In the Toxicity table, OD measurements are normalized by the uninduced OD measurement for each repressor.
* Value of 1.0 means non-toxic. Value below 1.0 indicates the degree of Toxicity.
* To compute Circuit Toxicity for each row in the truth table, multiply Toxicity values for reach repressor in that row of the truth table.
*
*/
public class Toxicity {
public static void initializeCircuitToxicity(LogicCircuit lc) { //cell growth = 1.0, avoids edge-case error when there are no logic gates.
for(Gate g: lc.get_output_gates()) {
g.get_toxicity().clear();
for(int i=0; i<g.get_logics().size(); ++i) {
g.get_toxicity().add(1.00);
}
}
}
/**
* Interpolate OD value (get weighted average) for nearest input RPUs from the ToxicityTable.
* Do this for all rows in truth table.
*
*/
public static void evaluateGateToxicity(Gate g) {
if(g.get_variable_names().size() == 1) { //multi-input toxicity not handled.
String var = g.get_variable_names().get(0);
if (g.get_toxtable().size() == 0) {
//System.out.println("no toxicity data for " + g.Name);
//System.exit(-1);
ArrayList<Double> toxicity = new ArrayList<Double>();
ArrayList<Double> input_rpu_rows = g.get_inrpus().get(var);
for (int i = 0; i < input_rpu_rows.size(); ++i) {
toxicity.add(1.0);
}
g.set_toxicity(toxicity);
} else {
ArrayList<Double> toxicity = new ArrayList<Double>();
ArrayList<Double> input_rpu_rows = g.get_inrpus().get(var);
for (int i = 0; i < input_rpu_rows.size(); ++i) {
double incoming_rpu = input_rpu_rows.get(i);
double tox_score = 1.0;
//if incoming rpu is below the first titration rpu
if (incoming_rpu < g.get_toxtable().get(0).get_x()) {
tox_score = g.get_toxtable().get(0).get_y();
}
//if incoming rpu is above the last titration rpu
else if (incoming_rpu > g.get_toxtable().get(g.get_toxtable().size() - 1).get_x()) {
tox_score = g.get_toxtable().get(g.get_toxtable().size() - 1).get_y();
}
//if incoming rpu is in the titration range, use weighted average of the two surrounding titration points
else {
//...search titrations until titration > incoming rpu
for (int t = 0; t < g.get_toxtable().size(); ++t) {
if (incoming_rpu < g.get_toxtable().get(t).get_x()) {
double lower_rpu = Math.log10(g.get_toxtable().get(t - 1).get_x());
double upper_rpu = Math.log10(g.get_toxtable().get(t).get_x());
double lower_tox = g.get_toxtable().get(t - 1).get_y();
double upper_tox = g.get_toxtable().get(t).get_y();
double weight = (Math.log10(incoming_rpu) - lower_rpu) / (upper_rpu - lower_rpu);
double weighted_avg = (lower_tox * (1 - weight)) + (upper_tox * weight);
tox_score = weighted_avg;
//tox_score = tox_table.get(Name.Repressor(g)).get(t - 1);
//for example,
// input_rpu = 16
// rpu titration 8.44 = tox 0.12 for QacR
// rpu titration 17.52 = tox 0.05 for QacR
// weighted_avg_tox = 0.051
break;
}
}
}
if (tox_score > 1.0)
tox_score = 1.0;
if (tox_score < 0.01)
tox_score = 0.01;
toxicity.add(tox_score);
}
g.set_toxicity(toxicity);
}
}
}
/**
* For each row in the truth table of the output gate(s),
* overall circuit Toxicity will have a multiplicative score for all repressors.
*
* All output gates will have the same Toxicity scores.
*
*/
public static void evaluateCircuitToxicity(LogicCircuit lc, GateLibrary gate_library){
ArrayList<Double> circuit_toxicity = new ArrayList<Double>();
for(int i=0; i<lc.get_output_gates().get(0).get_logics().size(); ++i) { //rows in truth table
double row_toxicity = 1.0;
for(Gate g: lc.get_logic_gates()) {
g.set_toxtable(gate_library.get_GATES_BY_NAME().get(g.Name).get_toxtable());
evaluateGateToxicity(g);
row_toxicity = row_toxicity * g.get_toxicity().get(i);
if(row_toxicity < 0.01) {
row_toxicity = 0.01;
}
}
circuit_toxicity.add(row_toxicity);
}
for(Gate g: lc.get_output_gates()) {
g.set_toxicity(circuit_toxicity);
}
}
/**
* A gate Toxicity score == worst Toxicity score among all rows of the truth table
*/
public static double mostToxicRow(Gate g) {
return Collections.min(g.get_toxicity());
/*double most_toxic_row = 1.0; //initialize to highest possible value
for(int i=0; i<g.get_toxicity().size(); ++i) {
if(g.get_toxicity().get(i) < most_toxic_row) {
most_toxic_row = g.get_toxicity().get(i);
}
}
return most_toxic_row;*/
}
/**
* A gate Toxicity score == worst Toxicity score among all rows of the truth table
*/
public static double mostToxicRow(LogicCircuit lc) {
//output gate toxicity = circuit gate toxicity with multiplicative growth value,
//all output gates will have the same toxicity values.
//TODO can consider allowing the user to specify a toxicity curve for an output gene.
Double min_growth = 1.0;
for(Gate g: lc.get_output_gates()) {
if(!g.get_toxicity().isEmpty()) {
if (Collections.min(g.get_toxicity()) < min_growth) {
min_growth = Collections.min(g.get_toxicity());
}
}
}
return min_growth;
/*double most_toxic_row = 1.0; //initialize to highest possible value
for(double tox: lc.get_output_gates().get(0).get_toxicity()) {
if(tox < most_toxic_row) {
most_toxic_row = tox;
}
}
return most_toxic_row;*/
}
/**
* Print a table of growth values for each logic gate an output gate.
*
* @param lc
* @return
*/
public static String writeToxicityTable(LogicCircuit lc) {
String s = "";
s += String.format("%14s", "truth table") + "\t";
for(int j=lc.get_logic_gates().size()-1; j>=0; --j) {
Gate gate = lc.get_logic_gates().get(j);
if (gate.get_logics().size() > 0 && gate.get_toxicity().size() > 0){
s += String.format("%7s", gate.Group) + "\t";
}
}
s += String.format("%11s", "circuit") + "\t";
s += "\n";
//all output gates will have the same growth values, calculated by multiplying all logic gate growth_values
//so we can just output the circuit growth once, which is why the 0'th index is used
for(int i=0; i<lc.get_output_gates().get(0).get_logics().size(); ++i){
s += String.format("%14s", lc.getLogicRow(i)) + "\t";
for(int j=lc.get_logic_gates().size()-1; j>=0; --j) {
Gate gate = lc.get_logic_gates().get(j);
if (gate.get_logics().size() > 0 && gate.get_toxicity().size() > 0){
s += String.format("%7s", String.format("%3.2f",gate.get_toxicity().get(i))) + "\t";
}
}
s += String.format("%11s", String.format("%3.2f",lc.get_output_gates().get(0).get_toxicity().get(i))) + "\t";
s += "\n";
}
return s;
}
}