001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.nbio.structure.align; 022 023 024import org.biojava.nbio.structure.Atom; 025import org.biojava.nbio.structure.Structure; 026import org.biojava.nbio.structure.StructureTools; 027import org.biojava.nbio.structure.align.ce.ConfigStrucAligParams; 028import org.biojava.nbio.structure.align.client.PdbPair; 029import org.biojava.nbio.structure.align.model.AFPChain; 030import org.biojava.nbio.structure.align.util.AtomCache; 031import org.biojava.nbio.structure.align.util.SynchronizedOutFile; 032import org.biojava.nbio.structure.align.xml.AFPChainXMLConverter; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036import java.io.File; 037import java.io.FileOutputStream; 038import java.io.OutputStreamWriter; 039import java.util.concurrent.Callable; 040import java.util.zip.GZIPOutputStream; 041 042/** 043 * Simple Callable Class that calculates a pairwise alignment in a different 044 * thread, so that multiple pairwise alignments can be run in parallel 045 * (examples: all-to-all alignments, DB search alignments). 046 * Adapted to a more general implementation since 4.1.0, because before it 047 * was thought for DB search only. 048 * 049 * @author Aleix Lafita 050 */ 051public class CallableStructureAlignment implements Callable<AFPChain> { 052 053 private final static Logger logger = LoggerFactory.getLogger( 054 CallableStructureAlignment.class); 055 056 //Structure information 057 private PdbPair pair; 058 private AtomCache cache; 059 private Atom[] ca1; 060 private Atom[] ca2; 061 062 //File output information - for DB searches 063 private SynchronizedOutFile outFile; 064 private File outFileDir; 065 066 //Algorithm information 067 private String algorithmName; 068 private ConfigStrucAligParams params; 069 070 /** 071 * Default constructor. Used in DB search. 072 * Instantiates an empty object, everything has to be set independently. 073 */ 074 public CallableStructureAlignment() {} 075 076 /** 077 * Constructor for all-to-all alignment calculation. 078 * Used for MultipleMC seed alignment calculation, for example. 079 * 080 * @param ca1 Atoms to align of the first structure 081 * @param ca2 Atoms to align of the second structure 082 * @param algorithmName the pairwise aligner algorithm to use, a new 083 * instance will be created for each thread. 084 * @param params parameter bean for the alignment. 085 */ 086 public CallableStructureAlignment(Atom[] ca1, Atom[] ca2, String algorithmName, ConfigStrucAligParams params){ 087 this.ca1 = ca1; 088 this.ca2 = ca2; 089 this.algorithmName = algorithmName; 090 this.params = params; 091 } 092 093 @Override 094 public AFPChain call() throws Exception { 095 096 //Prepare the alignment algorithm 097 StructureAlignment algorithm = StructureAlignmentFactory.getAlgorithm(algorithmName); 098 if (params!=null) algorithm.setParameters(params); 099 100 AFPChain afpChain = null; 101 try { 102 //Download the Atoms if they are not provided from the outisde (DB searches usually) 103 if (ca1 == null) { 104 Structure structure1 = cache.getStructure(pair.getName1()); 105 ca1 = StructureTools.getRepresentativeAtomArray(structure1); 106 } else ca1 = StructureTools.cloneAtomArray(ca1); 107 108 Structure structure2 = null; 109 if (ca2 == null) { 110 structure2 = cache.getStructure(pair.getName2()); 111 ca2 = StructureTools.getRepresentativeAtomArray(structure2); 112 } else ca2 = StructureTools.cloneAtomArray(ca2); 113 114 afpChain = algorithm.align(ca1, ca2); 115 116 if (pair!=null){ 117 afpChain.setName1(pair.getName1()); 118 afpChain.setName2(pair.getName2()); 119 } 120 121 //Do not output anything if there is no File information 122 if (outFile != null && outFileDir != null){ 123 String desc2 = structure2.getPDBHeader().getDescription(); 124 if ( desc2 == null) 125 desc2=""; 126 afpChain.setDescription2(desc2); 127 String result = afpChain.toDBSearchResult(); 128 logger.info("{}", result); 129 130 outFile.write(result); 131 132 String xml = AFPChainXMLConverter.toXML(afpChain, ca1, ca2); 133 writeXML(outFileDir,pair.getName1(), pair.getName2(), xml); 134 } 135 136 } catch ( Exception e){ 137 logger.error("Exception: ", e); 138 } 139 return afpChain; 140 } 141 142 public PdbPair getPair() { 143 return pair; 144 } 145 146 public void setPair(PdbPair pair) { 147 this.pair = pair; 148 } 149 150 public AtomCache getCache() { 151 return cache; 152 } 153 154 public void setCache(AtomCache cache) { 155 this.cache = cache; 156 } 157 158 public SynchronizedOutFile getOutFile() { 159 return outFile; 160 } 161 162 public void setOutFile(SynchronizedOutFile outFile) { 163 this.outFile = outFile; 164 } 165 166 public Atom[] getCa1() { 167 return ca1; 168 } 169 170 public void setCa1(Atom[] ca1) { 171 this.ca1 = ca1; 172 } 173 174 private void writeXML(File outFileF, String name1, String name2, String xml) 175 { 176 try{ 177 // Create file 178 File newF = new File(outFileF, "dbsearch_" +name1+"_" + name2+".xml.gz"); 179 180 FileOutputStream fstream = new FileOutputStream(newF); 181 182 GZIPOutputStream gz = new GZIPOutputStream(fstream); 183 OutputStreamWriter writer = new OutputStreamWriter(gz); 184 writer.write(xml); 185 writer.close(); 186 } catch (Exception e){//Catch exception if any 187 logger.error("Exception: ", e); 188 } 189 } 190 191 public void setOutputDir(File outFileF) { 192 this.outFileDir = outFileF; 193 } 194 195 public void setAlgorithmName(String algorithmName) { 196 this.algorithmName = algorithmName; 197 } 198 199 public void setParameters(ConfigStrucAligParams parameters) { 200 this.params = parameters; 201 } 202}