1 /* vast2mage.c
2  *
3  * ===========================================================================
4  *
5  *                            PUBLIC DOMAIN NOTICE
6  *            National Center for Biotechnology Information (NCBI)
7  *
8  *  This software/database is a "United States Government Work" under the
9  *  terms of the United States Copyright Act.  It was written as part of
10  *  the author's official duties as a United States Government employee and
11  *  thus cannot be copyrighted.  This software/database is freely available
12  *  to the public for use. The National Library of Medicine and the U.S.
13  *  Government do not place any restriction on its use or reproduction.
14  *  We would, however, appreciate having the NCBI and the author cited in
15  *  any work or product based on this material
16  *
17  *  Although all reasonable efforts have been taken to ensure the accuracy
18  *  and reliability of the software and data, the NLM and the U.S.
19  *  Government do not and cannot warrant the performance or results that
20  *  may be obtained by using this software or data. The NLM and the U.S.
21  *  Government disclaim all warranties, express or implied, including
22  *  warranties of performance, merchantability or fitness for any particular
23  *  purpose.
24  *
25  * ===========================================================================
26  *
27  * File Name: vast2mage.c
28  *
29  * Author: Tom Madej
30  *
31  * Version Creation Date: 03/12/98
32  *
33  * $Log: vast2mage.c,v $
34  * Revision 6.10  2000/01/31 19:59:12  lewisg
35  * fix output of date in pdb header
36  *
37  * Revision 6.9  1999/10/13 20:19:35  zimmerma
38  * DZ: Removed use of temporary files - html output redirected to stdout
39  *
40  * Revision 6.8  1999/05/07 13:53:02  zimmerma
41  * Changed call to InstBSAnnotSet() to pass Chain and SlaveChain params
42  *
43  * Revision 6.7  1999/02/10 14:42:53  addess
44  * fixed problem with not being able to read new files
45  *
46  * Revision 6.6  1998/10/14  17:17:35  addess
47  * sending aligned chains to MAGE
48  *
49  * Revision 6.5  1998/07/17  18:47:15  madej
50  * Allow Mage to work with Vast Search.
51  *
52  * Revision 6.4  1998/06/11  19:11:20  madej
53  * Part of a fix for a problem in Vast search.
54  *
55  * Revision 6.3  1998/05/19  20:21:17  madej
56  * Add general WWW routines for running on Sun servers.
57  *
58  * Revision 6.2  1998/03/30  19:13:25  madej
59  * Changes by Ken Addess.
60  *
61  * Revision 6.1  1998/03/12  17:10:06  madej
62  * First official version of vast2mage.c
63  *
64  */
65 
66 #include <stdio.h>
67 #include <ncbi.h>
68 #include <accentr.h>
69 #include <netentr.h>
70 #include <www.h>
71 #include <sys/resource.h>
72 #include <mmdbapi.h>
73 #include <mmdbapi1.h>
74 #include "vastlocl.h"
75 #include "mmdblocl.h"
76 #include "mmdbdata.h"
77 #include "vast2mage.h"
78 #include "vastsrv.h"
79 
80 static char *BaseURL;
81 static FILE *OutputFile = NULL;
82 static char OutputName[200];
83 #define CPUTIME_MAX 120
84 
85 extern CharPtr KineColors[];
86 extern Int1 ColorNumKinBB[];
87 extern Int1 ColorNumKinSC[];
88 extern Int1 ColorNumKinAC[];
89 
90 
AlignKinVirt(PFB pfbThis,Int4 iModel,Int4 iIndex,Pointer ptr)91 void LIBCALLBACK AlignKinVirt(PFB pfbThis, Int4 iModel,  Int4 iIndex, Pointer ptr)
92 {
93 
94   PMBD pmbdThis = NULL;
95   PALD paldFrom = NULL;
96   PALD paldTo = NULL;
97   FILE *pFile = NULL;
98   PMAD pmadFrom = NULL;
99   PMGD pmgdFrom = NULL;
100 
101   if (!pfbThis) return;
102   if (ptr) pFile = (FILE *) ptr;
103   if (pfbThis->bMe == (Byte) AM_MBD)
104       {
105         pmbdThis = (PMBD) pfbThis;
106 	if (!(pmbdThis->bWhat & (Byte) BOND_VIRTUAL)) return;
107 	paldFrom = GetLocation(GetAtomLocs(pmbdThis->pmadFrom, iModel), 0, ' ');
108 	paldTo = GetLocation(GetAtomLocs(pmbdThis->pmadTo, iModel), 0, ' ');
109 	pmadFrom = pmbdThis->pmadFrom;
110 	pmgdFrom = (PMGD) pmadFrom->pfbParent;
111 	if (paldFrom && paldTo)
112 	 {
113 	  if (iIndex)
114            {  /* do aligned region */
115              if (pmgdFrom->bReserved)
116 	       {
117                 AddLineKin(pFile, paldFrom, paldTo);
118                }
119            }
120           else
121             if (!pmgdFrom->bReserved)
122               {
123                 AddLineKin(pFile, paldFrom, paldTo);
124               }
125 	 }
126 
127       }
128   return;
129 }
130 
131 
132 
133 
134 
AlignKinHeader(PDNMS pdnmsThis,FILE * pFile,Boolean master)135 void LIBCALL AlignKinHeader(PDNMS pdnmsThis,  FILE *pFile, Boolean master)
136 {
137 
138    Int4 depyear, depday;
139    PMSD pmsdThis = NULL;
140    BiostrucSourcePtr pbssThis = NULL;
141    ValNodePtr pvnThis = NULL;
142    BiostrucHistoryPtr pbshThis = NULL;
143    CharPtr pcAuthors = NULL;
144 
145    if (!pdnmsThis) return;
146    pmsdThis = (PMSD) pdnmsThis->data.ptrvalue;
147    pvnThis = ValNodeFindNext(pmsdThis->pbsBS->descr,NULL,BiostrucDescr_history);
148    if (pvnThis)
149      {
150       pbshThis = (BiostrucHistoryPtr) pvnThis->data.ptrvalue;
151       pbssThis = pbshThis->data_source;
152      }
153    if (!pmsdThis->pcPDBName) pmsdThis->pcPDBName = StringSave("1UNK");
154    fprintf(pFile,"Alignment Summary\n\n");
155    if (master)
156       fprintf(pFile,"Master:\n%s\n\n", pmsdThis->pcChemName);
157    else
158       fprintf(pFile,"Slave:\n%s\n\n", pmsdThis->pcChemName);
159    fflush(pFile);
160    fprintf(pFile,"MMDB Accession:\n%ld\n\n", (long) pmsdThis->iMMDBid);
161    fprintf(pFile,"PDB Accession:\n%s\n\n", pmsdThis->pcPDBName);
162    fflush(pFile);
163    if (pbssThis)
164      {
165    	depyear = pbssThis->database_entry_date->data[1];
166    	depday = pbssThis->database_entry_date->data[3];
167 
168    	fprintf(pFile,"PDB Deposition:\n%2d-%3s-%02d\n\n",
169                    (int) depday,
170                    NCBI_months[pbssThis->database_entry_date->data[2]-1],
171                    (int) depyear%100);
172      }
173   fprintf(pFile,"Class:\n%s\n\n", pmsdThis->pcPdbClass);
174   fflush(pFile);
175   fprintf(pFile,"Source:\n%s\n\n", pmsdThis->pcPdbSource);
176   fflush(pFile);
177   pcAuthors =  AuthorListPDB(pmsdThis->pbsBS) ;
178   if (pcAuthors)
179     {
180       fprintf(pFile,"Authors:\n%s\n\n", pcAuthors);
181       fflush(pFile);
182       MemFree(pcAuthors);
183     }
184 
185   return;
186 }
187 
188 
WriteKinAlign(Int2 iStructure,Int2 iModel,PDNMS pdnmsThis,FILE * pFile,Int2 iColor,Byte bKinRender,CharPtr pcComposition)189 static Int2 WriteKinAlign(Int2 iStructure, Int2 iModel,  PDNMS pdnmsThis,
190 		FILE *pFile,  Int2 iColor, Byte bKinRender, CharPtr pcComposition)
191 {
192    Int2 iTest = 1;
193    Int2 iHold = 0;
194    PMSD pmsdThis = NULL;
195    PDNMM pdnmmThis = NULL;
196    PMMD pmmdThis = NULL;
197    PMBD pmbdThis = NULL;
198    PVNMB pvnmbThis = NULL;
199    CharPtr pcColor = NULL;
200    Boolean bFirst = TRUE;
201    CharPtr pcKinMolName = NULL;
202 
203     /* this ignores ensembles - only animates models */
204     pmsdThis = (PMSD) pdnmsThis->data.ptrvalue;
205     iHold = SetActiveModel(PFBFromDN(pdnmsThis),iModel);
206 
207 
208  	  fprintf(pFile, "@group {%s %d} animate dominant\n",pmsdThis->pcPDBName, iStructure);
209 	  fflush(pFile);
210 	  if (bKinRender & (Byte) KIN_VIRTUAL)
211 	    {
212 		 fprintf(pFile, "@subgroup {aligned %s} master= {Aligned V}\n", pmsdThis->pcPDBName);
213 		 fflush(pFile);
214 		 /* walk the molecules - do the aligned portions */
215 		 pdnmmThis = pmsdThis->pdnmmHead;
216 		 while (pdnmmThis)
217 		   {
218 		       ProgMon("Writing Kinemage");
219 		       pmmdThis = (PMMD) pdnmmThis->data.ptrvalue;
220 		       if (pmmdThis->bReserved)
221 			  {
222 			     pcKinMolName = GetKinMolName(pmmdThis);
223 			     pcColor = KineColors[ColorNumKinAC[(iStructure % KIN_COLOR_NUM)]];
224 			     fprintf(pFile, "@vectorlist {%s %s %d} color= %s\n",pcKinMolName,
225 					 pmmdThis->pcMolName, (int)pdnmmThis->choice , pcColor);
226 			     fflush(pFile);
227 			     iTest = TraverseOneModel(pmmdThis->pdnmgHead,TRAVERSE_BOND,iModel,1,pFile,
228 						(pNodeFunc)AlignKinVirt);
229 			     pvnmbThis = pmmdThis->pvnmbIRBHead;
230 			     while (pvnmbThis) /* walk the IRBonds by hand */
231 				{
232 				    pmbdThis = (PMBD) pvnmbThis->data.ptrvalue;
233 				    AlignKinVirt((PFB) pmbdThis, iModel,  1,  pFile);
234 				    pvnmbThis = pvnmbThis->next;
235 				}
236 
237 			  }
238 
239 		       pdnmmThis = pdnmmThis->next;
240 		   }
241                  fprintf(pFile, "@subgroup {unaligned %s} master= {Unaligned V}\n", pmsdThis->pcPDBName);
242 		 fflush(pFile);
243 		 /* walk the molecules - do the unaligned portions */
244 		 pdnmmThis = pmsdThis->pdnmmHead;
245 		 while (pdnmmThis)
246 		   {
247 		       ProgMon("Writing Kinemage");
248 		       pmmdThis = (PMMD) pdnmmThis->data.ptrvalue;
249 		       if (pmmdThis->bReserved)
250 			  {
251 			     pcKinMolName = GetKinMolName(pmmdThis);
252 			     pcColor = KineColors[ColorNumKinBB[(iStructure % KIN_COLOR_NUM)]];
253 			     fprintf(pFile, "@vectorlist {%s %s %d} color= %s\n",pcKinMolName,
254 					 pmmdThis->pcMolName, (int)pdnmmThis->choice , pcColor);
255 			     fflush(pFile);
256 			     iTest = TraverseOneModel(pmmdThis->pdnmgHead,TRAVERSE_BOND,iModel,0,pFile,
257 						(pNodeFunc)AlignKinVirt);
258 			     pvnmbThis = pmmdThis->pvnmbIRBHead;
259 			     while (pvnmbThis) /* walk the IRBonds by hand */
260 				{
261 				    pmbdThis = (PMBD) pvnmbThis->data.ptrvalue;
262 				    AlignKinVirt((PFB) pmbdThis, iModel,  0,  pFile);
263 				    pvnmbThis = pvnmbThis->next;
264 				}
265 
266 			  }
267 
268 		       pdnmmThis = pdnmmThis->next;
269 		   }
270 	    }
271 	  pdnmmThis = pmsdThis->pdnmmHead;
272 	  if (bKinRender & (Byte) KIN_HET)
273 	    {
274 	          bFirst = TRUE;
275 		 /* walk the molecules */
276 		  while (pdnmmThis)
277 		   {
278 		        pmmdThis = (PMMD) pdnmmThis->data.ptrvalue;
279 			if (pmmdThis)
280 		        if ((pmmdThis->bWhat == AM_HET) ||
281                             (pmmdThis->bWhat == AM_POLY) ||
282 			    (pmmdThis->bWhat == AM_ION))
283 			  {
284 			     if (bFirst)
285 			       {
286 				    fprintf(pFile, "@subgroup {hets} master= {Hets}\n");
287 				    fflush(pFile);
288 				    bFirst = FALSE;
289 			       }
290 			     pcColor = KineColors[ColorNumKinBB[(pdnmmThis->choice % KIN_COLOR_NUM)]];
291 			     pcKinMolName = GetKinMolName(pmmdThis);
292 			     fprintf(pFile, "@vectorlist {%s %d} color= %s\n",pcKinMolName,
293 					(int)pdnmmThis->choice , pcColor);
294 			     fflush(pFile);
295 			     iTest = TraverseOneModel(pmmdThis->pdnmgHead,TRAVERSE_BOND,iModel,0,pFile,
296 						(pNodeFunc)WriteKinHet);
297 			     pvnmbThis = pmmdThis->pvnmbIRBHead;
298 			     while (pvnmbThis) /* walk the IRBonds by hand */
299 				{
300 				    pmbdThis = (PMBD) pvnmbThis->data.ptrvalue;
301 				    WriteKinHet((PFB) pmbdThis, iModel,  0,  pFile);
302 				    pvnmbThis = pvnmbThis->next;
303 				}
304 			  }
305 
306 		       pdnmmThis = pdnmmThis->next;
307 		   }
308 	    }
309 	 if ((bKinRender & (Byte) KIN_HET) && (pmsdThis->bWhat & (Byte) AM_ION))
310            {
311 	     fprintf(pFile,  "@subgroup {Ions} \n");
312 	     fflush(pFile);
313       	     iTest = TraverseOneModel(pmsdThis->pdnmmHead, TRAVERSE_ATOM,
314 					iModel, iColor, (Pointer) pFile,
315 					(pNodeFunc)WriteKinIon);
316 	     fflush(pFile);
317 	   }
318     return iTest;
319 }
320 
321 
322 
WriteKinPairAlign(PDNMS pdnmsMaster,PDNMS pdnmsSlave,FILE * pFile,Int2 iColor,Byte bKinRender)323 static Int2 WriteKinPairAlign(PDNMS pdnmsMaster,
324                            PDNMS pdnmsSlave,
325                            FILE *pFile,
326                            Int2 iColor, Byte bKinRender)
327 {
328 
329     Int2 iIndex = 1;
330     Int2 iTest = 0;
331     CharPtr pcComposition1 = NULL;
332     CharPtr pcComposition2 = NULL;
333 
334     PMSD pmsdThis = NULL;
335     PDNML pdnmlThis = NULL;
336     PMLD  pmldThis = NULL;
337     Int2 iPDBCount = 0;
338 
339     if (pdnmsSlave == NULL)
340 	return 0;
341 
342     fprintf(pFile, "@text\n");
343     fprintf(pFile, "NCBI - Generated Kinemage File Alignment From MMDB\n\n");
344     fflush(pFile);
345 
346     if (!pdnmsMaster) return iTest;
347     pmsdThis = (PMSD) pdnmsMaster->data.ptrvalue;
348     if (!(pmsdThis->bMe == (Byte) AM_MSD)) return iTest;
349 
350     ResolveAlignChain(pdnmsMaster);
351     ResolveAlignChain(pdnmsSlave);  /* moves up bReserved value into pmmd->bReserved to flag mols for align */
352 
353     AlignKinHeader(pdnmsMaster, pFile, TRUE);
354     AlignKinHeader(pdnmsSlave, pFile, FALSE);
355     pcComposition1 = WriteKinSeq(pdnmsMaster, pFile); /* puts sequence, returns composition string */
356     pcComposition2 = WriteKinSeq(pdnmsSlave, pFile); /* puts sequence, returns composition string */
357 
358     fprintf(pFile, "@kinemage %d\n", (int)iIndex);
359     fprintf(pFile, "@caption\n");
360     fprintf(pFile, "\nVAST derived alignment \n" );
361     fflush(pFile);
362 
363     iTest = WriteKinAlign(1, 0,  pdnmsMaster, pFile,  iColor,  bKinRender, pcComposition1);
364     fflush(pFile);
365     iTest = WriteKinAlign(2, 0,  pdnmsSlave, pFile, iColor, bKinRender, pcComposition2);
366     fflush(pFile);
367     if (pcComposition1) MemFree(pcComposition1);
368     if (pcComposition2) MemFree(pcComposition2);
369 
370     return iTest;
371 }
372 
373 
374 
375 /* Display a structural alignment by a direct call to Kinemage. */
376 
VastToMage(WWWInfoPtr www_info)377 Boolean LIBCALL VastToMage(WWWInfoPtr www_info)
378 {
379 	FILE *pFile = NULL;
380 	FILE *pIn = NULL;
381 	Char pcBuf[100], pcLine[256], giBuf[20], URL[200];
382 	CharPtr pcTest, pcL1 = NULL, www_arg;
383 	CharPtr JobID = NULL, pcPass;
384 	Int4 GetGi, Fid, Fsid, iFileExists = 0, indx, complexity;
385 	BiostrucAnnotSetPtr pbsa = NULL;
386 	BiostrucAnnotSetPtr pbsaShort = NULL;
387 	PDNMS pdnmsMaster = NULL, pdnmsSlave = NULL;
388 	Int2 iTest = 0, iPDB = 0, iColor, ret;
389 	AsnIoPtr aip = NULL;
390 	Byte bRender;
391 	Char *IPAddress = getenv("REMOTE_HOST");
392         Boolean Chain;
393 
394 	if ((indx = WWWFindName(www_info, "uid")) < 0) {
395 		printf("Content-type: text/html\n\n");
396 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
397 		printf("<h3>No accession (PDB ID) was input - nothing to report.</h3>\n");
398 		return 0;
399 	}
400 
401 	www_arg = WWWGetValueByIndex(www_info, indx);
402 
403 	if (isdigit(www_arg[0]))
404 		GetGi = (Int4) atoi(www_arg);
405 	else {
406 		printf("Content-type: text/html\n\n");
407 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
408 		printf("<h3>Non-numeric MMDB-id input - no results.</h3>\n");
409 		return 0;
410 	}
411 
412 	/* vsid and pass are to look at alignments from VAST Search */
413 	if ((indx = WWWFindName(www_info, "vsid")) >= 0) {
414 		www_arg = WWWGetValueByIndex(www_info, indx);
415 		JobID = StringSave(www_arg);
416 
417 		if ((indx = WWWFindName(www_info, "pass")) < 0) {
418 			printf("Content-type: text/html\n\n");
419 			printf("<body bgcolor = \"#f0f0f0\">\n");
420 			printf("<h2>VAST SEARCH</h2>\n");
421 			printf("<h3>Password required.</h3>\n");
422 			return 0;
423 		}
424 		else {
425 			www_arg = WWWGetValueByIndex(www_info, indx);
426 			pcPass = StringSave(www_arg);
427 
428 			if ((ret = Check_VastSearch_Password(pcPass, JobID)) != 1) {
429 				if (ret == 2) return 0;
430 				printf("Content-type: text/html\n\n");
431 				printf("<body bgcolor = \"#f0f0f0\">\n");
432 				printf("<h2>VAST SEARCH</h2>\n");
433 				printf("<h3>Incorrect password.</h3>\n");
434 				return 0;
435 			}
436 		}
437 	}
438 
439 	if ((indx = WWWFindName(www_info, "hit")) < 0) {
440 		printf("Content-type: text/html\n\n");
441 		printf("<body bgcolor = \"#f0f0f0\">\n");
442 		printf("<br>\n<h2>No alignment was selected!</h2>\n");
443 		printf("<h3>Please click on a box in the leftmost column of the table.</h3>\n");
444 		return 0;
445 	}
446 
447 	www_arg = WWWGetValueByIndex(www_info, indx);
448 
449 	if (isdigit(www_arg[0]))
450 		Fid = (Int4) atoi(www_arg);
451 	else {
452 		printf("Content-type: text/html\n\n");
453 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
454 		printf("<h3>Non-numeric slave alignment code - no results.</h3>\n");
455 		return 0;
456 	}
457 
458 	if ((indx = WWWFindName(www_info, "chaindom")) < 0) {
459 		printf("Content-type: text/html\n\n");
460 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
461 		printf("<h3>No feature set ID (master alignment code) - nothing to report.</h3>\n");
462 		return 0;
463 	}
464 
465 	www_arg = WWWGetValueByIndex(www_info, indx);
466 
467 	if (isdigit(www_arg[0]))
468 		Fsid = (Int4) atoi(www_arg);
469 	else {
470 		printf("Content-type: text/html\n\n");
471 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
472 		printf("<h3>Non-numeric master alignment code - no results.</h3>\n");
473 		return 0;
474 	}
475 
476         if ((indx = WWWFindName(www_info, "chn_complexity")) < 0)
477             Chain = TRUE;
478         else
479         {
480           www_arg = WWWGetValueByIndex(www_info, indx);
481           complexity =(Int2)atoi(www_arg);
482 
483           if (complexity) Chain = TRUE;
484           else Chain = FALSE;
485         }
486 
487         /* action == 0 indicates MIME; action == 1 is text; action == 2 is save */
488 	if ((indx = WWWFindName(www_info, "action")) < 0)
489 		iPDB = 0;
490 	else {
491 		www_arg = WWWGetValueByIndex(www_info, indx);
492 
493 		if (isdigit(www_arg[0]))
494 			iPDB = (Int4) atoi(www_arg);
495 		else
496 			iPDB = 0;
497 	}
498 
499 	if (VASTInit() != TRUE) {
500 		printf("Content-type: text/html\n\n");
501 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
502 		printf("<h3>Can't find VAST data on server.\n");
503 		printf("Contact info@ncbi.nlm.nih.gov</h3>\n");
504 		return 0;
505 	}
506 
507 	OpenMMDBAPI((POWER_VIEW /* ^ FETCH_ENTREZ */), NULL);
508 
509 	if (JobID == NULL)
510 		pbsa = VASTBsAnnotSetGet(Fsid);
511 	else
512 		pbsa = LocalGetFeatureSet(GetGi, Fsid, JobID);
513 
514 	if (pbsa == NULL) {
515 		printf("Content-type: text/html\n\n");
516 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
517 		printf("<h3>No master alignment record exists for %ld.</h3>\n", (long) GetGi);
518 		return 0;
519 	}
520 
521 	pbsaShort = BiostrucAnnotSetGetByFid(pbsa, Fid, Fsid);
522 
523 	if (pbsaShort == NULL) {
524 		printf("Content-type: text/html\n\n");
525 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
526 		printf("<h3>Can't find alignment record.</h3>\n");
527 		return 0;
528 	}
529 
530 	if (MMDBInit() == FALSE) {
531 		printf("Content-type: text/html\n\n");
532 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
533 		printf("<h3>MMDBInit failed.</h3>\n");
534 		return 0;
535 	}
536 
537 	/* A note to myself for when I get back from Xmas break.  This is the situation:
538 	 * The call to VastToMage is failing on the check where pdnmsSlave == NULL.  For
539 	 * some reason the slave structure is not getting loaded into the global data
540 	 * structure.  It appears that the next function call to InstBSAnnotSet() loads
541 	 * the master structure.  However, I do not see where the slave structure gets
542 	 * loaded.  Absurdly enough, though, the locally compiled vastsrv works fine, and
543 	 * the slave is indeed getting properly loaded there.
544 	 *
545 	 * I think I see it.  There are massive differences between the local mmdbapi1.c
546 	 * and the checked-in one.  In particular, BiostrucAddFeature is grossly different
547 	 * between the two.  It looks like the slaves are loaded in the latter routine.
548 	 * InstBSAnnotSet calls BiostrucAddFeature.
549 	 */
550 
551         InstBSAnnotSet(pbsaShort, JobID, Chain, VSPATH); /* now uses mmdbapi1 version */
552 	pdnmsMaster = GetMasterModelstruc();
553 	/***** This is causing a problem at line 126, where pmsdThis->pbsBS does not exist!
554 	pdnmsMaster = GetSelectedModelstruc();
555 	*****/
556 
557 	if (pdnmsMaster == NULL) {
558 		printf("Content-type: text/html\n\n");
559 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
560 		printf("<h3>Unable to load master structure.</h3>\n");
561 		return 0;
562 	}
563 
564 	pdnmsSlave = GetSlaveModelstruc();
565 
566 	if (pdnmsSlave == NULL) {
567 		printf("Content-type: text/html\n\n");
568 		printf("<h2>VASTSERV Error (VastToMage)</h2>\n");
569 		printf("<h3>Unable to load slave structure.</h3>\n");
570 		return 0;
571 	}
572 
573 	/* Kinemage file generation */
574 
575      if (iPDB == 2)
576      {
577        fprintf(stdout, "Content-type: application/octet-stream\n\n");
578      }
579      else if (iPDB == 1)
580      {
581        fprintf(stdout, "Content-type: text/html\n\n");
582        fprintf(stdout, "<HTML><body><pre>\n");
583      }
584      else
585        fprintf(stdout, "Content-type: chemical/x-kinemage\n\n"); /* MIME */
586 
587 	bRender = (Byte) (KIN_VIRTUAL | KIN_HET);
588 	iColor = KIN_COLOR_NUMBER;
589 	iTest = WriteKinPairAlign(pdnmsMaster, pdnmsSlave, stdout, iColor, bRender);
590 
591   if (!iTest)
592     {
593       printf("Content-type: text/html\n\n");
594       printf("<h2>Error</h2>\n");
595       printf("Kinemage File write failed on Server.<p>\n");
596       RemoveTempFiles();
597       CloseMMDBAPI();
598       MMDBFini();
599       VASTFini();
600       exit(1);
601     }
602 
603   fflush(stdout);
604 
605   CloseMMDBAPI();
606   MMDBFini();
607   VASTFini();
608   RemoveTempFiles();
609   return 0;
610 
611 } /* end of VastToMage */
612 
613