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.xml;
022
023import org.biojava.nbio.structure.Atom;
024import org.biojava.nbio.structure.StructureException;
025import org.biojava.nbio.structure.align.model.AFPChain;
026import org.biojava.nbio.structure.align.util.AlignmentTools;
027import org.biojava.nbio.structure.jama.Matrix;
028import org.biojava.nbio.core.util.PrettyXMLWriter;
029
030import java.io.IOException;
031import java.io.PrintWriter;
032import java.io.StringWriter;
033
034
035
036public class AFPChainXMLConverter {
037
038
039        /** Convert an afpChain to a simple XML representation
040         *
041         * @param afpChain
042         * @return XML representation of the AFPCHain
043         */
044        public synchronized static String toXML(AFPChain afpChain, Atom[] ca1, Atom[]ca2) throws IOException{
045                StringWriter result = new StringWriter();
046                toXML(afpChain,result,ca1,ca2);
047                return result.toString();
048        }
049
050        /** Write the XML representation to a StringWriter
051         *
052         * @param afpChain
053         * @param swriter
054         * @throws IOException
055         */
056        public synchronized static void toXML(AFPChain afpChain, StringWriter swriter,Atom[] ca1, Atom[]ca2) throws IOException{
057
058                PrintWriter writer = new PrintWriter(swriter);
059                PrettyXMLWriter xml = new PrettyXMLWriter(writer);
060
061                xml.openTag("AFPChain");
062
063                printXMLHeader(xml,afpChain);
064
065
066                // that is the initial alignment...
067                // we don't serialize that at the present.
068                //int[] blockResSize = afpChain.getBlockResSize();
069                //int[][][] blockResList = afpChain.getBlockResList();
070
071
072                // get the alignment blocks
073                int blockNum = afpChain.getBlockNum();
074                //int[] optLen       = afpChain.getOptLen();
075                //int[] blockSize    = afpChain.getBlockSize();
076                for(int bk = 0; bk < blockNum; bk ++) {
077
078                        xml.openTag("block");
079
080                        printXMLBlockHeader(xml,afpChain, bk);
081
082                        if ( ca1 == null || ca2 == null) {
083                                try {
084                                        printXMLEQRKnownPositions(xml,afpChain,bk);
085                                } catch (StructureException ex ){
086                                        throw new IOException(ex.getMessage());
087                                }
088                        }
089                        else
090                                printXMLEQRInferPositions(xml, afpChain,bk,ca1,ca2);
091
092                        printXMLMatrixShift(xml, afpChain, bk);
093
094                        xml.closeTag("block");
095                }
096
097                xml.closeTag("AFPChain");
098
099                writer.close();
100
101
102        }
103
104
105
106        private static void printXMLEQRKnownPositions(PrettyXMLWriter xml,
107                        AFPChain afpChain, int blockNr) throws IOException, StructureException{
108                int[] optLen       = afpChain.getOptLen();
109
110
111                String[][][] pdbAln = afpChain.getPdbAln();
112                if ( pdbAln == null){
113                        throw new StructureException("Can't convert to XML without known the PDB coordinates. Please provide Ca atoms and call toXML(afpChain,ca1, ca2)");
114                }
115
116                for ( int eqrNr = 0 ; eqrNr < optLen[blockNr] ; eqrNr++ ){
117
118                        String pdbResnum1 = pdbAln[blockNr][0][eqrNr];
119                        String pdbResnum2 = pdbAln[blockNr][1][eqrNr];
120
121                        //System.out.println(eqrNr + " got resnum: " + pdbResnum1 + " " + pdbResnum2);
122
123                        String[] spl1 = pdbResnum1.split(":");
124                        String[] spl2 = pdbResnum2.split(":");
125
126                        String chain1 = spl1[0];
127                        String pdbres1 = spl1[1];
128
129                        String chain2 = spl2[0];
130                        String pdbres2 = spl2[1];
131
132                        xml.openTag("eqr");
133                        xml.attribute("eqrNr", String.valueOf(eqrNr));
134                        xml.attribute("pdbres1",pdbres1);
135                        xml.attribute("chain1", chain1);
136                        xml.attribute("pdbres2",pdbres2);
137                        xml.attribute("chain2", chain2);
138                        xml.closeTag("eqr");
139                }
140        }
141
142
143        public static void printXMLEQRInferPositions(PrettyXMLWriter xml,
144                        AFPChain afpChain, int bk, Atom[] ca1, Atom[] ca2)  throws IOException{
145
146                int[] optLen       = afpChain.getOptLen();
147
148                if ( optLen == null)
149                        return;
150
151                int[][][] optAln   = afpChain.getOptAln();
152
153
154                for ( int pos=0;pos< optLen[bk];pos++){
155                        int pos1 = optAln[bk][0][pos];
156                        int pos2 = optAln[bk][1][pos];
157                        xml.openTag("eqr");
158                        xml.attribute("eqrNr", String.valueOf(pos));
159                        xml.attribute("pdbres1",ca1[pos1].getGroup().getResidueNumber().toString());
160                        xml.attribute("chain1", ca1[pos1].getGroup().getChain().getName());
161                        xml.attribute("pdbres2",ca2[pos2].getGroup().getResidueNumber().toString());
162                        xml.attribute("chain2", ca2[pos2].getGroup().getChain().getName());
163
164                        xml.closeTag("eqr");
165                        //System.out.println("aligned position: " + pos1  + ":" + pos2 +
166                        //" pdbresnum " + ca1[pos1].getGroup().getResidueNumber().toString() + " " +
167                        //ca1[pos1].getParent().getPDBName()+":" +
168                        //ca2[pos2].getGroup().getResidueNumber().toString() + " " + ca2[pos2].getParent().getPDBName());
169
170                }
171
172        }
173
174
175        private static void printXMLBlockHeader(PrettyXMLWriter xml,
176                        AFPChain afpChain,int blockNr) throws IOException{
177
178                int bk = blockNr;
179                int[] blockSize    = afpChain.getBlockSize();
180                //if ( blockSize[bk] == 0) {
181                //      return;
182                //}
183                int[] blockGap     = afpChain.getBlockGap();
184
185                double[]blockScore = afpChain.getBlockScore();
186                double[] blockRmsd = afpChain.getBlockRmsd();
187
188                xml.attribute("blockNr", String.valueOf(bk));
189                xml.attribute("blockSize", String.valueOf(blockSize[bk]));
190                xml.attribute("blockScore", String.format("%5.2f",blockScore[bk]).trim());
191                xml.attribute("blockRmsd", String.format("%5.2f",blockRmsd[bk]).trim());
192                xml.attribute("blockGap", String.valueOf(blockGap[bk]));
193
194        }
195
196
197        private static void printXMLMatrixShift(PrettyXMLWriter xml,
198                        AFPChain afpChain, int blockNr)  throws IOException {
199
200                Matrix[] ms     = afpChain.getBlockRotationMatrix();
201                if ( ms == null || ms.length == 0)
202                        return;
203
204                Matrix matrix = ms[blockNr];
205                if ( matrix == null)
206                        return;
207                xml.openTag("matrix");
208
209
210                for (int x=0;x<3;x++){
211                        for (int y=0;y<3;y++){
212                                String key = "mat"+(x+1)+(y+1);
213                                xml.attribute(key,String.format("%.6f",matrix.get(x,y)));
214                        }
215                }
216                xml.closeTag("matrix");
217
218                Atom[]   shifts = afpChain.getBlockShiftVector();
219                Atom shift = shifts[blockNr];
220                xml.openTag("shift");
221                xml.attribute("x", String.format("%.3f",shift.getX()));
222                xml.attribute("y", String.format("%.3f",shift.getY()));
223                xml.attribute("z", String.format("%.3f",shift.getZ()));
224                xml.closeTag("shift");
225
226        }
227
228
229        public static String toXML(AFPChain afpChain) throws IOException{
230
231                return toXML(afpChain, null, null);
232        }
233
234
235        public static void printXMLHeader(PrettyXMLWriter xml, AFPChain afpChain) throws IOException{
236                xml.attribute("name1", afpChain.getName1());
237                xml.attribute("name2", afpChain.getName2());
238                xml.attribute("method", afpChain.getAlgorithmName());
239                xml.attribute("version" , afpChain.getVersion());
240                xml.attribute("alnLength", afpChain.getAlnLength() + "");
241                xml.attribute("blockNum", afpChain.getBlockNum() + "");
242                xml.attribute("gapLen", afpChain.getGapLen() + "");
243                xml.attribute("optLength", afpChain.getOptLength() + "");
244                xml.attribute("totalLenIni", afpChain.getTotalLenIni() + "");
245
246                xml.attribute("alignScore", String.format("%5.2f", afpChain.getAlignScore() ).trim());
247                xml.attribute("chainRmsd",  String.format("%5.2f", afpChain.getChainRmsd() ).trim());
248                xml.attribute("identity",String.format("%5.4f", afpChain.getIdentity() ).trim());
249                xml.attribute("normAlignScore", String.format("%5.2f",afpChain.getNormAlignScore()).trim());
250                xml.attribute("probability", String.format("%.2e", afpChain.getProbability() ).trim());
251                xml.attribute("similarity", String.format("%5.4f", afpChain.getSimilarity() ).trim());
252
253                xml.attribute("similarity1", afpChain.getCoverage1() + "");
254                xml.attribute("similarity2", afpChain.getCoverage2() + "");
255                xml.attribute("totalRmsdIni", String.format("%5.2f",afpChain.getTotalRmsdIni() ).trim());
256                xml.attribute("totalRmsdOpt", String.format("%5.2f",afpChain.getTotalRmsdOpt() ).trim());
257                xml.attribute("ca1Length", afpChain.getCa1Length()+"");
258                xml.attribute("ca2Length", afpChain.getCa2Length()+"");
259                xml.attribute("afpNum",afpChain.getAfpSet().size()+"");
260                xml.attribute("alignScoreUpdate",String.format("%5.2f",afpChain.getAlignScoreUpdate()).trim());
261                xml.attribute("time", String.format("%d",afpChain.getCalculationTime()));
262                if ( afpChain.getTMScore() != -1){
263                        xml.attribute("tmScore", String.format("%.2f",afpChain.getTMScore()));
264                }
265
266                // test if alignment is CP:
267                if ( ! AlignmentTools.isSequentialAlignment(afpChain,false)) {
268                        xml.attribute("cp","true");
269                }
270        }
271}