package org.cellocad.MIT.dnacompiler;
import org.cellocad.adaptors.ucfadaptor.UCFAdaptor;
import java.util.ArrayList;
import java.util.HashSet;
public class GeneticLocationWriter {
public static void set_bp_range_for_parts(ArrayList<Part> parts, int start_bp, int end_bp) {
for(Part p: parts) {
p.set_start(start_bp);
p.set_end(end_bp);
}
}
public static void insertModulePartsIntoGeneticLocations(LogicCircuit lc, UCF ucf) {
UCFAdaptor ucf_adaptor = new UCFAdaptor();
if(!ucf_adaptor.getLocationName(ucf, "sensor").equals("")) {
for (ArrayList<Part> sensor_module : lc.get_sensor_module_parts() ) {
Integer start_bp = ucf_adaptor.getLocationStartBP(ucf, "sensor");
Integer end_bp = ucf_adaptor.getLocationStartBP(ucf, "sensor");
GeneticLocationWriter.set_bp_range_for_parts(sensor_module, start_bp, end_bp);
}
}
if(!ucf_adaptor.getLocationName(ucf, "circuit").equals("")) {
for (ArrayList<Part> circuit_module : lc.get_circuit_module_parts()) {
Integer start_bp = ucf_adaptor.getLocationStartBP(ucf, "circuit");
Integer end_bp = ucf_adaptor.getLocationStartBP(ucf, "circuit");
GeneticLocationWriter.set_bp_range_for_parts(circuit_module, start_bp, end_bp);
}
}
if(!ucf_adaptor.getLocationName(ucf, "output").equals("")) {
for (ArrayList<Part> output_module : lc.get_output_module_parts()) {
Integer start_bp = ucf_adaptor.getLocationStartBP(ucf, "output");
Integer end_bp = ucf_adaptor.getLocationStartBP(ucf, "output");
GeneticLocationWriter.set_bp_range_for_parts(output_module, start_bp, end_bp);
}
}
String sensor_location = ucf_adaptor.getLocationName(ucf, "sensor");
String circuit_location = ucf_adaptor.getLocationName(ucf, "circuit");
String output_location = ucf_adaptor.getLocationName(ucf, "output");
if(!sensor_location.equals("")) {
//if sensor module has its own unique location
if (!sensor_location.equals(circuit_location) && !sensor_location.equals(output_location)) {
writeModulesToLocation(
ucf,
"sensor",
lc.get_sensor_module_parts(),
lc.get_sensor_plasmid_parts() //the list of plasmids is generated by fn call
);
}
}
if(!circuit_location.equals("")) {
//if circuit module has its own unique location
if (!circuit_location.equals(sensor_location) && !circuit_location.equals(output_location)) {
writeModulesToLocation(
ucf,
"circuit",
lc.get_circuit_module_parts(),
lc.get_circuit_plasmid_parts() //the list of plasmids is generated by fn call
);
}
}
if(!output_location.equals("")) {
//if output module has its own unique location
if (!output_location.equals(circuit_location) && !output_location.equals(sensor_location)) {
writeModulesToLocation(
ucf,
"output",
lc.get_output_module_parts(),
lc.get_output_plasmid_parts() //the list of plasmids is generated by fn call
);
}
}
if(!sensor_location.equals("") && !sensor_location.equals("")) {
//if sensor and circuit share a location
if (sensor_location.equals(circuit_location) && !sensor_location.equals(output_location)) {
writeModulesToLocation(
ucf,
"sensor",
lc.get_sensor_module_parts(),
"circuit",
lc.get_circuit_module_parts(),
lc.get_circuit_plasmid_parts() //the list of plasmids is generated by fn call
);
}
}
if(!sensor_location.equals("") && !output_location.equals("")) {
//if sensor and output share a location
if (sensor_location.equals(output_location) && !sensor_location.equals(circuit_location)) {
writeModulesToLocation(
ucf,
"sensor",
lc.get_sensor_module_parts(),
"output",
lc.get_output_module_parts(),
lc.get_output_plasmid_parts() //the list of plasmids is generated by fn call
);
}
}
if(!circuit_location.equals("") && !output_location.equals("")) {
//if circuit and output share a location
if (circuit_location.equals(output_location) && !circuit_location.equals(sensor_location)) {
writeModulesToLocation(
ucf,
"circuit",
lc.get_circuit_module_parts(),
"output",
lc.get_output_module_parts(),
lc.get_circuit_plasmid_parts() //the list of plasmids is generated by fn call
);
}
}
if(!sensor_location.equals("") && !circuit_location.equals("") && !output_location.equals("")) {
//if sensor and circuit and output share a location
if (circuit_location.equals(output_location) && circuit_location.equals(sensor_location)) {
writeModulesToLocation(
ucf,
"sensor",
lc.get_sensor_module_parts(),
"circuit",
lc.get_circuit_module_parts(),
"output",
lc.get_output_module_parts(),
lc.get_circuit_plasmid_parts() //the list of plasmids is generated by fn call
);
}
}
}
public static void writeModulesToLocation(
UCF ucf,
String module_name,
ArrayList<ArrayList<Part>> module_parts,
ArrayList<ArrayList<Part>> plasmid_list
) {
UCFAdaptor ucf_adaptor = new UCFAdaptor();
ArrayList<String> genbank_lines = ucf_adaptor.getLocationGenbankLines(ucf, module_name);
Integer start_bp = ucf_adaptor.getLocationStartBP(ucf, module_name);
Integer end_bp = ucf_adaptor.getLocationEndBP(ucf, module_name);
String backbone_seq = PlasmidUtil.extractNucleotideSequenceFromGenbankLines(genbank_lines);
//Step 1. Make a sorted list of unique cut sites
HashSet<Integer> cut_sites_map = new HashSet<Integer>();
cut_sites_map.add(1);
cut_sites_map.add(start_bp);
cut_sites_map.add(end_bp);
cut_sites_map.add(backbone_seq.length());
ArrayList<Integer> cut_sites = new ArrayList<Integer>(cut_sites_map);
java.util.Collections.sort(cut_sites);
// System.out.println(cut_sites.toString());
//Step 2. Divide the backbone into segments based on the cuts. Excise gaps when appropriate.
ArrayList<Part> backbone_parts = new ArrayList<Part>();
for(int i=0; i<cut_sites.size()-1; ++i) {
if(cut_sites.get(i+1) > cut_sites.get(i)) {
Part p = new Part("backbone", "backbone", backbone_seq.substring(cut_sites.get(i)-1, cut_sites.get(i+1)-1));
p.set_start(cut_sites.get(i));
p.set_end(cut_sites.get(i+1));
//excision of gap sequence
if(p.get_start() == start_bp && p.get_end() == end_bp) {
continue;
}
backbone_parts.add(p);
}
}
for(ArrayList<Part> module: module_parts) {
//Step 3. Assign the part start/end bp numbers according to the genetic location start/end from the UCF.
//Note that all parts will share the same start/end.
//Sorting parts based on start/end values will maintain the current order if start/end are identical.
for (Part p : module) {
p.set_start(start_bp);
p.set_end(end_bp);
}
ArrayList<Part> plasmid = new ArrayList<Part>();
plasmid.addAll(module);
for(Part p: backbone_parts) {
plasmid.add(new Part(p));
}
//Step 4. Sort parts based on start/end bp number, then renumber all parts in the plasmid.
//Sorting MUST maintain the intended part order.
PlasmidUtil.sortPartsByStartBP(plasmid);
PlasmidUtil.renumberPlasmidBases(plasmid, 0);
//Step 5. Append plasmid to list of plasmids.
plasmid_list.add(plasmid);
}
}
public static void writeModulesToLocation(
UCF ucf,
String module_name_1,
ArrayList<ArrayList<Part>> module_parts_1,
String module_name_2,
ArrayList<ArrayList<Part>> module_parts_2,
ArrayList<ArrayList<Part>> plasmid_list
) {
UCFAdaptor ucf_adaptor = new UCFAdaptor();
ArrayList<String> genbank_lines_1 = ucf_adaptor.getLocationGenbankLines(ucf, module_name_1);
Integer start_bp_1 = ucf_adaptor.getLocationStartBP(ucf, module_name_1);
Integer end_bp_1 = ucf_adaptor.getLocationEndBP(ucf, module_name_1);
ArrayList<String> genbank_lines_2 = ucf_adaptor.getLocationGenbankLines(ucf, module_name_2);
Integer start_bp_2 = ucf_adaptor.getLocationStartBP(ucf, module_name_2);
Integer end_bp_2 = ucf_adaptor.getLocationEndBP(ucf, module_name_2);
String backbone_seq = PlasmidUtil.extractNucleotideSequenceFromGenbankLines(genbank_lines_1);
//Step 1. Make a sorted list of unique cut sites
HashSet<Integer> cut_sites_map = new HashSet<Integer>();
cut_sites_map.add(1);
cut_sites_map.add(start_bp_1);
cut_sites_map.add(end_bp_1);
cut_sites_map.add(start_bp_2);
cut_sites_map.add(end_bp_2);
cut_sites_map.add(backbone_seq.length());
ArrayList<Integer> cut_sites = new ArrayList<Integer>(cut_sites_map);
java.util.Collections.sort(cut_sites);
// System.out.println(cut_sites.toString());
//Step 2. Divide the backbone into segments based on the cuts. Excise gaps when appropriate.
ArrayList<Part> backbone_parts = new ArrayList<Part>();
for(int i=0; i<cut_sites.size()-1; ++i) {
if(cut_sites.get(i+1) > cut_sites.get(i)) {
Part p = new Part("backbone", "backbone", backbone_seq.substring(cut_sites.get(i)-1, cut_sites.get(i+1)-1));
p.set_start(cut_sites.get(i));
p.set_end(cut_sites.get(i+1));
//excision of gap sequence
if(p.get_start() == start_bp_1 && p.get_end() == end_bp_1) {
continue;
}
if(p.get_start() == start_bp_2 && p.get_end() == end_bp_2) {
continue;
}
backbone_parts.add(p);
}
}
for(ArrayList<Part> module1: module_parts_1) {
for(ArrayList<Part> module2: module_parts_2) { //nested loop will enumerate all combinations of module variants
//Step 3. Assign the part start/end bp numbers according to the genetic location start/end from the UCF.
//Note that all parts will share the same start/end.
//Sorting parts based on start/end values will maintain the current order if start/end are identical.
for (Part p : module1) {
p.set_start(start_bp_1);
p.set_end(end_bp_1);
}
for (Part p : module2) {
p.set_start(start_bp_2);
p.set_end(end_bp_2);
}
ArrayList<Part> plasmid = new ArrayList<Part>();
plasmid.addAll(module1);
plasmid.addAll(module2);
for(Part p: backbone_parts) {
plasmid.add(new Part(p));
}
//Step 4. Sort parts based on start/end bp number, then renumber all parts in the plasmid.
//Sorting MUST maintain the intended part order.
PlasmidUtil.sortPartsByStartBP(plasmid);
PlasmidUtil.renumberPlasmidBases(plasmid, 0);
//Step 5. Append plasmid to list of plasmids.
plasmid_list.add(plasmid);
}
}
}
public static void writeModulesToLocation(
UCF ucf,
String module_name_1,
ArrayList<ArrayList<Part>> module_parts_1,
String module_name_2,
ArrayList<ArrayList<Part>> module_parts_2,
String module_name_3,
ArrayList<ArrayList<Part>> module_parts_3,
ArrayList<ArrayList<Part>> plasmid_list
) {
UCFAdaptor ucf_adaptor = new UCFAdaptor();
ArrayList<String> genbank_lines_1 = ucf_adaptor.getLocationGenbankLines(ucf, module_name_1);
Integer start_bp_1 = ucf_adaptor.getLocationStartBP(ucf, module_name_1);
Integer end_bp_1 = ucf_adaptor.getLocationEndBP(ucf, module_name_1);
ArrayList<String> genbank_lines_2 = ucf_adaptor.getLocationGenbankLines(ucf, module_name_2);
Integer start_bp_2 = ucf_adaptor.getLocationStartBP(ucf, module_name_2);
Integer end_bp_2 = ucf_adaptor.getLocationEndBP(ucf, module_name_2);
ArrayList<String> genbank_lines_3 = ucf_adaptor.getLocationGenbankLines(ucf, module_name_3);
Integer start_bp_3 = ucf_adaptor.getLocationStartBP(ucf, module_name_3);
Integer end_bp_3 = ucf_adaptor.getLocationEndBP(ucf, module_name_3);
String backbone_seq = PlasmidUtil.extractNucleotideSequenceFromGenbankLines(genbank_lines_1);
//Step 1. Make a sorted list of unique cut sites
HashSet<Integer> cut_sites_map = new HashSet<Integer>();
cut_sites_map.add(1);
cut_sites_map.add(start_bp_1);
cut_sites_map.add(end_bp_1);
cut_sites_map.add(start_bp_2);
cut_sites_map.add(end_bp_2);
cut_sites_map.add(start_bp_3);
cut_sites_map.add(end_bp_3);
cut_sites_map.add(backbone_seq.length());
ArrayList<Integer> cut_sites = new ArrayList<Integer>(cut_sites_map);
java.util.Collections.sort(cut_sites);
// System.out.println(cut_sites.toString());
//Step 2. Divide the backbone into segments based on the cuts. Excise gaps when appropriate.
ArrayList<Part> backbone_parts = new ArrayList<Part>();
for(int i=0; i<cut_sites.size()-1; ++i) {
if(cut_sites.get(i+1) > cut_sites.get(i)) {
Part p = new Part("backbone", "backbone", backbone_seq.substring(cut_sites.get(i)-1, cut_sites.get(i+1)-1));
p.set_start(cut_sites.get(i));
p.set_end(cut_sites.get(i+1));
//excision of gap sequence
if(p.get_start() == start_bp_1 && p.get_end() == end_bp_1) {
continue;
}
if(p.get_start() == start_bp_2 && p.get_end() == end_bp_2) {
continue;
}
if(p.get_start() == start_bp_3 && p.get_end() == end_bp_3) {
continue;
}
backbone_parts.add(p);
}
}
for(ArrayList<Part> module1: module_parts_1) {
for(ArrayList<Part> module2: module_parts_2) {
for(ArrayList<Part> module3: module_parts_3) { //nested loop will enumerate all combinations of module variants
//Step 3. Assign the part start/end bp numbers according to the genetic location start/end from the UCF.
//Note that all parts will share the same start/end.
//Sorting parts based on start/end values will maintain the current order if start/end are identical.
for (Part p : module1) {
p.set_start(start_bp_1);
p.set_end(end_bp_1);
}
for (Part p : module2) {
p.set_start(start_bp_2);
p.set_end(end_bp_2);
}
for (Part p : module3) {
p.set_start(start_bp_3);
p.set_end(end_bp_3);
}
ArrayList<Part> plasmid = new ArrayList<Part>();
plasmid.addAll(module1);
plasmid.addAll(module2);
plasmid.addAll(module3);
for(Part p: backbone_parts) {
plasmid.add(new Part(p));
}
//Step 4. Sort parts based on start/end bp number, then renumber all parts in the plasmid.
//Sorting MUST maintain the intended part order.
PlasmidUtil.sortPartsByStartBP(plasmid);
PlasmidUtil.renumberPlasmidBases(plasmid, 0);
//Step 5. Append plasmid to list of plasmids.
plasmid_list.add(plasmid);
}
}
}
}
}