package org.cellocad.adaptors.sboladaptor; import org.cellocad.MIT.dnacompiler.Args; import org.cellocad.MIT.dnacompiler.Gate; import org.cellocad.MIT.dnacompiler.LogicCircuit; import org.cellocad.MIT.dnacompiler.Part; import org.sbolstandard.core2.*; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Set; // TODO Needs to be generalized for other gate types public class SBOLCircuitWriter { /*********************************************************************** ***********************************************************************/ public String writeSBOLCircuit(String output_filename, LogicCircuit lc, ArrayList<Part> plasmid, String prefix, Args options) { _sequence_ontology_map.put("ribozyme", SequenceOntology.INSULATOR); _sequence_ontology_map.put("rbs", SequenceOntology.RIBOSOME_ENTRY_SITE); _sequence_ontology_map.put("cds", SequenceOntology.CDS); _sequence_ontology_map.put("terminator", SequenceOntology.TERMINATOR); _sequence_ontology_map.put("promoter", SequenceOntology.PROMOTER); _sequence_ontology_map.put("output", SequenceOntology.CDS); _document = new org.sbolstandard.core2.SBOLDocument(); _document.setDefaultURIprefix("http://cellocad.org"); _circuit_name = prefix.replace("-", "_"); ///////////////////////////////////////////// ////////// Populate circuit design data ///////////////////////////////////////////// setInteractionMap(lc); ///////////////////////////////////////////// ////////// Structural layer: component definitions ///////////////////////////////////////////// setCircuitComponentDefinition(plasmid); setPartComponentDefinitions(plasmid); setAnnotations(); ///////////////////////////////////////////// ////////// Functional layer: Module definitions, modules, functional components ///////////////////////////////////////////// setCircuitModuleDefinition(); setPartFunctionalComponents(); setProductionInteractions(plasmid); setRepressionInteractions(plasmid); setInducerInteractions(plasmid); ////////////////////////////////////////////////// /////////////// write to sbolDocument ////////////////////////////////////////////////// String output_filepath = options.get_output_directory() + "/" + output_filename; try { org.sbolstandard.core2.SBOLWriter.write(_document, output_filepath); } catch (Exception e) { e.printStackTrace(); } return _document.toString(); } /** * Annotate plasmid with start bp and end bp for each part */ public void setAnnotations() { int current_bp = 1; //part components were added in setPartComponentDefinitions for(Component c: _part_components) { String annotationID = "sequence_annotation_" + c.getDisplayId() + "_" + _annotation_index; ComponentDefinition cd = c.getDefinition(); Integer next_bp = current_bp; Set<Sequence> component_seq_set = cd.getSequences(); for(Sequence component_seq: component_seq_set) { next_bp += component_seq.getElements().length(); } SequenceAnnotation sequenceAnnotation = _circuit_component_definition.createSequenceAnnotation(annotationID, "locationID"+_annotation_index, current_bp, next_bp); sequenceAnnotation.setComponent(c.getIdentity()); _annotation_index++; current_bp = next_bp + 1; } } /** * Highest level in the functional layer. * Contains functional components (promoter, protein, inducer) and interactions between fc's. */ public void setCircuitModuleDefinition() { URI gateRoleURI = URI.create("http://cellocad.org/LogicCircuit"); _circuit_module_definition = _document.createModuleDefinition(_circuit_name + "_module"); _circuit_module_definition.addRole(gateRoleURI); } /** * Functional components for promoters and cds's. */ public void setPartFunctionalComponents() { for(ComponentDefinition part_cd: _part_component_definitions) { for (URI role : part_cd.getRoles()) { if (role.equals(_sequence_ontology_map.get("promoter")) || role.equals(_sequence_ontology_map.get("cds"))) { boolean fc_exists = false; for(FunctionalComponent fc: _circuit_module_definition.getFunctionalComponents()) { if(fc.getDisplayId().equals(part_cd.getDisplayId())) { fc_exists = true; } } if(!fc_exists) { FunctionalComponent partFunctionalComponent = _circuit_module_definition.createFunctionalComponent( part_cd.getDisplayId(), AccessType.PUBLIC, part_cd.getIdentity(), DirectionType.NONE ); } } } } } /** * The circuit plasmid is the highest level in structural layer. * Will include vector backbone if one was specified in the UCF genetic_locations collection. * Currently, I am not creating an SBOL document for each output plasmid, if the output module is on * a separate plasmid from the circuit module. * @param plasmid */ public void setCircuitComponentDefinition(ArrayList<Part> plasmid) { URI circuitTypeURI = URI.create("http://www.biopax.org/release/biopax-level3.owl#DnaRegion"); HashSet<URI> circuitTypeURIs = new HashSet<URI>(); circuitTypeURIs.add(circuitTypeURI); _circuit_component_definition = _document.createComponentDefinition(_circuit_name + "_circuit", circuitTypeURIs); String concatenated_plasmid_sequence = ""; for(Part p: plasmid) { concatenated_plasmid_sequence += p.get_seq(); //what if revcomp? } String sequenceDisplayID = _circuit_name + "_circuit" + "_sequence"; URI encodingURI = URI.create("http://www.chem.qmul.ac.uk/iubmb/misc/naseq.html"); Sequence s = _document.createSequence(sequenceDisplayID, concatenated_plasmid_sequence, encodingURI); } public void setProductionInteractions(ArrayList<Part> plasmid) { //production for(int i=0; i<_production_promoters.size(); ++i) { String promoter_name = _production_promoters.get(i); String protein_name = _production_proteins.get(i); Set<URI> geneticProductionTypes = new HashSet<URI>(); geneticProductionTypes.add(SystemsBiologyOntology.GENETIC_PRODUCTION); Set<URI> proteinTypeURIs = new HashSet<URI>(); proteinTypeURIs.add(URI.create("http://www.biopax.org/release/biopax-level3.owl#Protein")); boolean promoter_cd_exists = false; ComponentDefinition promoter_cd = null; for (ComponentDefinition cd : _document.getComponentDefinitions()) { if (cd.getDisplayId().equals(promoter_name)) { promoter_cd = cd; promoter_cd_exists = true; break; } } if (!promoter_cd_exists) { //promoter (likely driving output) is on a different plasmid continue; } boolean protein_cd_exists = false; ComponentDefinition protein_cd; for (ComponentDefinition cd : _document.getComponentDefinitions()) { if (cd.getDisplayId().equals(protein_name)) { protein_cd_exists = true; } } if (protein_cd_exists) { protein_cd = _document.getComponentDefinition(protein_name, ""); } else { protein_cd = _document.createComponentDefinition(protein_name, proteinTypeURIs); } boolean promoter_fc_exists = false; FunctionalComponent promoter_fc; for (FunctionalComponent fc : _circuit_module_definition.getFunctionalComponents()) { if (fc.getDisplayId().equals(promoter_cd.getDisplayId())) { promoter_fc_exists = true; } } if (promoter_fc_exists) { promoter_fc = _circuit_module_definition.getFunctionalComponent(promoter_cd.getDisplayId()); } else { promoter_fc = _circuit_module_definition.createFunctionalComponent( promoter_cd.getDisplayId(), AccessType.PUBLIC, promoter_cd.getIdentity(), DirectionType.NONE ); } //FunctionalComponent promoter_fc = _circuit_module_definition.getFunctionalComponent(promoter_name); boolean protein_fc_exists = false; FunctionalComponent protein_fc; for (FunctionalComponent fc : _circuit_module_definition.getFunctionalComponents()) { if (fc.getDisplayId().equals(protein_cd.getDisplayId())) { protein_fc_exists = true; } } if (protein_fc_exists) { protein_fc = _circuit_module_definition.getFunctionalComponent(protein_cd.getDisplayId()); } else { protein_fc = _circuit_module_definition.createFunctionalComponent( protein_cd.getDisplayId(), AccessType.PUBLIC, protein_cd.getIdentity(), DirectionType.NONE ); } String productionInteractionDisplayID = promoter_name + "_produces_" + protein_name; Interaction productionInteraction = _circuit_module_definition.createInteraction(productionInteractionDisplayID, geneticProductionTypes); String promoterParticipationID = promoter_name + "_participation"; String proteinParticipationID = protein_cd.getDisplayId() + "_participation"; //Add for CDS //(fn component for cds?) Participation production_promoter = productionInteraction.createParticipation(promoterParticipationID, promoter_fc.getDisplayId()); Participation production_regulator = productionInteraction.createParticipation(proteinParticipationID, protein_fc.getDisplayId()); //Do this again for the CDS //missing roles production_promoter.addRole(SystemsBiologyOntology.PROMOTER); production_regulator.addRole(SystemsBiologyOntology.PRODUCT); //CDS. production_cds.addRole(SystemsBiologyOntology.MODIFIER) } } public void setRepressionInteractions(ArrayList<Part> plasmid) { //repression for (String protein_name : _repression_map.keySet()) { String promoter_name = _repression_map.get(protein_name); Set<URI> inhibitionTypeURIs = new HashSet<URI>(); inhibitionTypeURIs.add(SystemsBiologyOntology.INHIBITION); FunctionalComponent protein_fc = _circuit_module_definition.getFunctionalComponent(protein_name); FunctionalComponent promoter_fc = _circuit_module_definition.getFunctionalComponent(promoter_name); String repressionInteractionDisplayID = protein_name + "_represses_" + promoter_name; Interaction repressionInteraction = _circuit_module_definition.createInteraction(repressionInteractionDisplayID, inhibitionTypeURIs); String promoterParticipationID = promoter_name + "_participation"; String proteinParticipationID = protein_name + "_participation"; Participation repression_regulator = repressionInteraction.createParticipation(proteinParticipationID, protein_fc.getDisplayId()); boolean plasmid_has_promoter = false; for (Part p : plasmid) { if (p.get_name().equals(promoter_name)) { plasmid_has_promoter = true; break; } } if (plasmid_has_promoter) { Participation repression_promoter = repressionInteraction.createParticipation(promoterParticipationID, promoter_fc.getDisplayId()); repression_promoter.addRole(SystemsBiologyOntology.PROMOTER); } //inhibitor URI inhibitorRole = SystemsBiologyOntology.INHIBITOR; repression_regulator.addRole(inhibitorRole); } } public void setInducerInteractions(ArrayList<Part> plasmid) { for (String protein_name : _repression_map.keySet()) { // non-covalent binding String inducer_name = ""; if(_noncovalent_map.containsKey(protein_name)) { inducer_name = _noncovalent_map.get(protein_name); } if(inducer_name != "") { //component definition type Set<URI> smallMoleculeTypeURIs = new HashSet<URI>(); smallMoleculeTypeURIs.add(URI.create("http://www.biopax.org/release/biopax-level3.owl#SmallMolecule")); //component definition type Set<URI> complexTypeURIs = new HashSet<URI>(); complexTypeURIs.add(URI.create("http://www.biopax.org/release/biopax-level3.owl#Complex")); ComponentDefinition inducer = _document.createComponentDefinition(inducer_name, smallMoleculeTypeURIs); String complex_name = inducer_name + "_" + protein_name + "_Complex"; ComponentDefinition complex = _document.createComponentDefinition(complex_name, complexTypeURIs); FunctionalComponent protein_fc = _circuit_module_definition.getFunctionalComponent(protein_name); FunctionalComponent inducer_fc = _circuit_module_definition.createFunctionalComponent( inducer.getDisplayId(), AccessType.PUBLIC, inducer.getIdentity(), DirectionType.NONE ); FunctionalComponent complex_fc = _circuit_module_definition.createFunctionalComponent( complex.getDisplayId(), AccessType.PUBLIC, complex.getIdentity(), DirectionType.NONE ); String complexInteractionDisplayID = protein_name + "_binds_" + inducer.getDisplayId(); Interaction noncovalentInteraction = _circuit_module_definition.createInteraction(complexInteractionDisplayID, complexTypeURIs); String inducerParticipationID = inducer.getDisplayId() + "_participation"; String complexParticipationID = complex.getDisplayId() + "_participation"; String proteinParticipationID = protein_name + "_participation"; //non-covalent interaction between Regulator and Small Molecule Participation complex_regulator = noncovalentInteraction.createParticipation(proteinParticipationID, protein_fc.getDisplayId()); Participation complex_inducer = noncovalentInteraction.createParticipation(inducerParticipationID, inducer_fc.getDisplayId()); Participation complex_complex = noncovalentInteraction.createParticipation(complexParticipationID, complex_fc.getDisplayId()); //ligand URI ligandRole = URI.create("http://identifiers.org/biomodels.sbo/SBO:0000280"); //complex URI complexRole = URI.create("http://identifiers.org/biomodels.sbo/SBO:0000253"); complex_inducer.addRole(ligandRole); complex_regulator.addRole(ligandRole); complex_complex.addRole(complexRole); } } } public void setPartComponentDefinitions(ArrayList<Part> plasmid) { for(Part p: plasmid) { //adds cd to document ComponentDefinition part_cd = getComponentDefinitionForPart(p); _part_component_definitions.add(part_cd); //adds seq to document Sequence part_seq = getComponentSequenceForPart(p); //seq is property of cd HashSet<URI> s_set = new HashSet<URI>(); s_set.add(part_seq.getIdentity()); part_cd.setSequences(s_set); if(_sequence_ontology_map.containsKey(p.get_type())) { part_cd.addRole(_sequence_ontology_map.get(p.get_type())); } _part_sequences.add(part_seq); boolean exists = false; for(Component c: _circuit_component_definition.getComponents()) { if(c.getDisplayId().equals(part_cd.getDisplayId() + "_component")) { _part_components.add(c); exists = true; } } if(! exists) { _part_components.add(_circuit_component_definition.createComponent(part_cd.getDisplayId() + "_component", AccessType.PUBLIC, part_cd.getIdentity())); } } } public Sequence getComponentSequenceForPart(Part p) { String sequenceDisplayID = p.get_name() + "_sequence"; //if exists, return the Sequence that was already created. for(Sequence s: _document.getSequences()) { if(s.getDisplayId().equals(sequenceDisplayID)) { return s; } } //if does not exists, create Sequence for part URI encodingURI = URI.create("http://www.chem.qmul.ac.uk/iubmb/misc/naseq.html"); Sequence s = _document.createSequence(sequenceDisplayID, p.get_seq(), encodingURI); return s; } public ComponentDefinition getComponentDefinitionForPart(Part p) { String cd_displayID = p.get_name(); //if exists, return the CD that was already created. for(ComponentDefinition cd: _document.getComponentDefinitions()) { if(cd.getDisplayId().equals(cd_displayID)) { return cd; } } //if does not exists, create CD for part URI partTypeURI = URI.create("http://www.biopax.org/release/biopax-level3.owl#DnaRegion"); HashSet<URI> partTypeURIs = new HashSet<URI>(); partTypeURIs.add(partTypeURI); ComponentDefinition partComponentDefinition = _document.createComponentDefinition(p.get_name(), partTypeURIs); if(_sequence_ontology_map.containsKey(p.get_type())) { partComponentDefinition.addRole(_sequence_ontology_map.get(p.get_type())); } return partComponentDefinition; } public void setInteractionMap(LogicCircuit lc) { for (Gate g : lc.get_Gates()) { if(g.Type == Gate.GateType.INPUT) { continue; } else if(g.Type == Gate.GateType.OUTPUT || g.Type == Gate.GateType.OUTPUT_OR) { for(Gate child: g.getChildren()) { _production_promoters.add(child.get_regulable_promoter().get_name()); _production_proteins.add(g.Regulator + "_protein"); } } else { String promoter_name = g.get_regulable_promoter().get_name(); _repression_map.put(g.Regulator + "_protein", promoter_name); for(Gate child: g.getChildren()) { _production_promoters.add(child.get_regulable_promoter().get_name()); _production_proteins.add(g.Regulator + "_protein"); } if(g.Inducer != "") { _noncovalent_map.put(g.Regulator + "_protein", g.Inducer); } } } } public void setCircuitName(String name) { _circuit_name = name; } private String _filepath = ""; public HashMap<String, URI> _sequence_ontology_map = new HashMap<String, URI>(); private String _circuit_name; private HashMap<String, String> _repression_map = new HashMap<String, String>(); private ArrayList<String> _production_promoters = new ArrayList<>(); private ArrayList<String> _production_proteins = new ArrayList<>(); //private HashMap<String, String> _production_map = new HashMap<String, String>(); private HashMap<String, String> _noncovalent_map = new HashMap<String, String>(); //private HashMap<String, String> _output_map = new HashMap<String, String>(); private ArrayList<Sequence> _part_sequences = new ArrayList<Sequence>(); private ArrayList<Component> _part_components = new ArrayList<>(); private ComponentDefinition _circuit_component_definition; private ArrayList<ComponentDefinition> _part_component_definitions = new ArrayList<ComponentDefinition>(); private ModuleDefinition _circuit_module_definition; //private ArrayList<FunctionalComponent> _part_functional_components = new ArrayList<FunctionalComponent>(); private int _annotation_index = 1; private SBOLDocument _document; }