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