~ubuntu-branches/ubuntu/edgy/ncbi-tools6/edgy

« back to all changes in this revision

Viewing changes to tools/blfmtutl.c

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese
  • Date: 2006-07-19 23:28:07 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20060719232807-et3cdmcjgmnyleyx
Tags: 6.1.20060507-3ubuntu1
Re-merge with Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
static char const rcsid[] = "$Id: blfmtutl.c,v 1.12 2005/11/22 13:44:24 coulouri Exp $";
 
1
static char const rcsid[] = "$Id: blfmtutl.c,v 1.18 2006/05/05 13:43:28 coulouri Exp $";
2
2
 
3
3
/* ===========================================================================
4
4
*
36
36
/*
37
37
* $Revision: 
38
38
* $Log: blfmtutl.c,v $
 
39
* Revision 1.18  2006/05/05 13:43:28  coulouri
 
40
* bump date
 
41
*
 
42
* Revision 1.17  2006/04/26 12:42:36  madden
 
43
* BlastSetUserErrorString and BlastDeleteUserErrorString moved from blastool.c to blfmtutl.c
 
44
*
 
45
* Revision 1.16  2006/04/07 19:46:59  coulouri
 
46
* correction to previous commit
 
47
*
 
48
* Revision 1.15  2006/04/07 18:38:19  coulouri
 
49
* bump version
 
50
*
 
51
* Revision 1.14  2006/01/24 18:38:47  papadopo
 
52
* from Mike Gertz: Fixed a typo in a name in a format string: Aravaind -> Aravind
 
53
*
 
54
* Revision 1.13  2005/12/29 19:55:04  madden
 
55
* Added functions to print tabular output
 
56
*
39
57
* Revision 1.12  2005/11/22 13:44:24  coulouri
40
58
* bump version
41
59
*
86
104
 
87
105
 
88
106
/* the version of BLAST. */
89
 
#define BLAST_ENGINE_VERSION "2.2.13"
90
 
#define BLAST_RELEASE_DATE "Nov-27-2005"
 
107
#define BLAST_ENGINE_VERSION "2.2.14"
 
108
#define BLAST_RELEASE_DATE "May-07-2006"
91
109
 
92
110
#define BUFFER_LENGTH 255
93
111
 
495
513
            add_string_to_bufferEx("Schäffer, Alejandro A., L. Aravind, Thomas L. Madden, ", &ret_buffer, &ret_buffer_length, TRUE);
496
514
        } else
497
515
          add_string_to_bufferEx("Reference for composition-based statistics:", &ret_buffer, &ret_buffer_length, TRUE);
498
 
          add_string_to_bufferEx("Schaffer, Alejandro A., L. Aravaind, Thomas L. Madden,", &ret_buffer, &ret_buffer_length, TRUE);
 
516
          add_string_to_bufferEx("Schaffer, Alejandro A., L. Aravind, Thomas L. Madden,", &ret_buffer, &ret_buffer_length, TRUE);
499
517
        }
500
518
        else {
501
519
          if (html) {
766
784
        return prune;
767
785
}
768
786
 
 
787
 
 
788
void PrintTabularOutputHeader(CharPtr blast_database, BioseqPtr query_bsp,
 
789
                              SeqLocPtr query_slp, CharPtr blast_program,
 
790
                              Int4 iteration, Boolean believe_query,
 
791
                              FILE *outfp)
 
792
{
 
793
   Char buffer[BUFFER_LENGTH+1];
 
794
   Boolean unlock_bioseq = FALSE;
 
795
 
 
796
   asn2ff_set_output(outfp, NULL);
 
797
   
 
798
   ff_StartPrint(0, 0, BUFFER_LENGTH, NULL);
 
799
 
 
800
   if (blast_program) {
 
801
      CharPtr program = StringSave(blast_program);
 
802
      Nlm_StrUpper(program);
 
803
      sprintf(buffer, "# %s %s [%s]", program, BlastGetVersionNumber(),
 
804
              BlastGetReleaseDate());
 
805
      MemFree(program);
 
806
      ff_AddString(buffer);
 
807
      NewContLine();
 
808
   }
 
809
 
 
810
   if (iteration > 0) {
 
811
      ff_AddString("# Iteration: ");
 
812
      ff_AddString(Ltostr((long) iteration, 1));
 
813
      NewContLine();
 
814
   }
 
815
 
 
816
   if (query_bsp || query_slp) {
 
817
      CharPtr title;
 
818
      const CharPtr str = "# Query: ";
 
819
      Int4 string_length = StrLen(str);
 
820
 
 
821
      ff_AddString(str);
 
822
 
 
823
      if (!query_bsp) {
 
824
         Int4 num_queries = ValNodeLen(query_slp);
 
825
         if (num_queries > 1) {
 
826
            /* Multiple queries: just print the number, without deflines. */
 
827
            sprintf(buffer, "%ld sequences", (long)num_queries);
 
828
            ff_AddString(buffer);
 
829
         } else {
 
830
            query_bsp = BioseqLockById(SeqLocId(query_slp));
 
831
            unlock_bioseq = TRUE;
 
832
         }
 
833
      }
 
834
      if (query_bsp) {
 
835
         if (query_bsp->id && believe_query) {
 
836
            SeqIdWrite(query_bsp->id, buffer, PRINTID_FASTA_LONG, 
 
837
                       BUFFER_LENGTH);
 
838
            if (StringNCmp(buffer, "lcl|", 4) == 0) {
 
839
               ff_AddString(buffer+4);
 
840
            } else {
 
841
               ff_AddString(buffer);
 
842
            }
 
843
            string_length += StrLen(buffer);
 
844
            ff_AddChar(' ');
 
845
            string_length++; /* to account for the space above. */
 
846
         }
 
847
 
 
848
         if ((title = BioseqGetTitle(query_bsp)) != NULL) { 
 
849
            /* We do this to keep the entire title on one line 
 
850
               (of length BUFFER_LENGTH). */
 
851
            StrNCpy(buffer, title, BUFFER_LENGTH - string_length);
 
852
            buffer[BUFFER_LENGTH - string_length] = NULLB;
 
853
            ff_AddString(buffer);
 
854
         }
 
855
 
 
856
         if (unlock_bioseq)
 
857
            BioseqUnlock(query_bsp);
 
858
      }
 
859
      NewContLine();
 
860
   }
 
861
   if (blast_database) {
 
862
      ff_AddString("# Database: ");
 
863
      ff_AddString(blast_database);
 
864
      NewContLine();
 
865
   }
 
866
   if (getenv("PRINT_SEQUENCES")) {
 
867
         ff_AddString("# Fields: Query id, Subject id, % identity, alignment length, mismatches, gap openings, q. start, q. end, s. start, s. end, e-value, bit score, query seq., subject seq.");
 
868
   } else {
 
869
         ff_AddString("# Fields: Query id, Subject id, % identity, alignment length, mismatches, gap openings, q. start, q. end, s. start, s. end, e-value, bit score");
 
870
   }
 
871
 
 
872
   ff_EndPrint();
 
873
}
 
874
 
 
875
static Int4
 
876
BlastBioseqGetNumIdentical(BioseqPtr q_bsp, BioseqPtr s_bsp, Int4 q_start,
 
877
                     Int4 s_start, Int4 length,
 
878
                     Uint1 q_strand, Uint1 s_strand)
 
879
{
 
880
   SeqLocPtr q_slp, s_slp;
 
881
   SeqPortPtr q_spp, s_spp;
 
882
   Int4 i, ident = 0;
 
883
   Uint1 q_res, s_res;
 
884
 
 
885
   if (!q_bsp || !s_bsp)
 
886
      return 0;
 
887
 
 
888
   q_slp = SeqLocIntNew(q_start, q_start+length-1, q_strand, q_bsp->id);
 
889
   s_slp = SeqLocIntNew(s_start, s_start+length-1, s_strand, s_bsp->id);
 
890
   if (ISA_na(q_bsp->mol))
 
891
      q_spp = SeqPortNewByLoc(q_slp, Seq_code_ncbi4na);
 
892
   else
 
893
      q_spp = SeqPortNewByLoc(q_slp, Seq_code_ncbistdaa);
 
894
   if (ISA_na(s_bsp->mol))
 
895
      s_spp = SeqPortNewByLoc(s_slp, Seq_code_ncbi4na);
 
896
   else
 
897
      s_spp = SeqPortNewByLoc(s_slp, Seq_code_ncbistdaa);
 
898
 
 
899
   for (i=0; i<length; i++) {
 
900
      while ((q_res = SeqPortGetResidue(q_spp)) != SEQPORT_EOF &&
 
901
             !IS_residue(q_res));
 
902
      while ((s_res = SeqPortGetResidue(s_spp)) != SEQPORT_EOF &&
 
903
             !IS_residue(s_res));
 
904
      if (q_res == SEQPORT_EOF || s_res == SEQPORT_EOF)
 
905
         break;
 
906
      else if (q_res == s_res)
 
907
         ident++;
 
908
   }
 
909
 
 
910
   SeqLocFree(q_slp);
 
911
   SeqLocFree(s_slp);
 
912
   SeqPortFree(q_spp);
 
913
   SeqPortFree(s_spp);
 
914
 
 
915
   return ident;
 
916
}
 
917
/* 
 
918
   Function to print results in tab-delimited format, given a SeqAlign list.
 
919
   q_shift and s_shift are the offsets in query and subject in case of a
 
920
   subsequence search 
 
921
*/
 
922
void BlastPrintTabulatedResults(SeqAlignPtr seqalign, BioseqPtr query_bsp,
 
923
                                SeqLocPtr query_slp, Int4 num_alignments, 
 
924
                                CharPtr blast_program, Boolean is_ungapped, 
 
925
                                Boolean believe_query, Int4 q_shift, 
 
926
                                Int4 s_shift, FILE *fp,
 
927
                                Boolean print_query_info)
 
928
{
 
929
   BlastPrintTabulatedResultsEx(seqalign, query_bsp, query_slp, num_alignments,
 
930
                                blast_program, is_ungapped, believe_query,
 
931
                                q_shift, s_shift, fp, NULL, print_query_info);
 
932
}
 
933
 
 
934
void BlastPrintTabulatedResultsEx(SeqAlignPtr seqalign, BioseqPtr query_bsp,
 
935
                                SeqLocPtr query_slp, Int4 num_alignments, 
 
936
                                CharPtr blast_program, Boolean is_ungapped, 
 
937
                                Boolean believe_query, Int4 q_shift, 
 
938
                                Int4 s_shift, FILE *fp, 
 
939
                                int *num_formatted, Boolean print_query_info)
 
940
{
 
941
   BlastPrintTabularResults(seqalign, query_bsp, query_slp, num_alignments,
 
942
      blast_program, is_ungapped, FALSE, believe_query,
 
943
      q_shift, s_shift, fp, num_formatted, print_query_info);
 
944
}
 
945
 
 
946
void BlastPrintTabularResults(SeqAlignPtr seqalign, BioseqPtr query_bsp,
 
947
        SeqLocPtr query_slp, Int4 num_alignments, CharPtr blast_program, 
 
948
        Boolean is_ungapped, Boolean is_ooframe, Boolean believe_query, 
 
949
        Int4 q_shift, Int4 s_shift, FILE *fp, int *num_formatted, 
 
950
        Boolean print_query_info)
 
951
{
 
952
   SeqAlignPtr sap, sap_tmp = NULL;
 
953
   FloatHi perc_ident, bit_score, evalue;
 
954
   Int4 numseg, num_gap_opens, num_mismatches, num_ident, score;
 
955
   Int4 number, align_length, index, i;
 
956
   Int4 q_start, q_end, s_start, s_end;
 
957
   Char bit_score_buff[10];
 
958
   CharPtr eval_buff;
 
959
   Boolean is_translated;
 
960
   SeqIdPtr query_id, old_query_id = NULL, subject_id, old_subject_id = NULL;
 
961
   BioseqPtr subject_bsp=NULL;
 
962
   Char query_buffer[BUFFER_LENGTH+1], subject_buffer[BUFFER_LENGTH+1];
 
963
   DenseSegPtr dsp;
 
964
   StdSegPtr ssp = NULL;
 
965
   DenseDiagPtr ddp = NULL;
 
966
   AlignSumPtr asp = NULL;
 
967
   CharPtr defline, title;
 
968
   SeqLocPtr slp;
 
969
   Int4 alignments_count;
 
970
 
 
971
   is_translated = (StringCmp(blast_program, "blastn") &&
 
972
                    StringCmp(blast_program, "blastp"));
 
973
   
 
974
   if (is_translated) {
 
975
      asp = MemNew(sizeof(AlignSum));
 
976
      asp->matrix = load_default_matrix();
 
977
      asp->is_aa = TRUE;
 
978
      asp->ooframe = is_ooframe;
 
979
   }
 
980
 
 
981
   if (is_ungapped)
 
982
      sap_tmp = SeqAlignNew();
 
983
 
 
984
   slp = query_slp;
 
985
   if (query_bsp)
 
986
      query_id = query_bsp->id;
 
987
 
 
988
   /* Evalue buffer is dynamically allocated to avoid compiler warnings 
 
989
      in calls to ScoreAndEvalueToBuffers. */
 
990
   eval_buff = Malloc(10);
 
991
 
 
992
   for (sap = seqalign; sap; sap = sap->next) {
 
993
      if (query_slp)
 
994
         query_id = TxGetQueryIdFromSeqAlign(sap);
 
995
      if (SeqIdComp(query_id, old_query_id) != SIC_YES) {
 
996
         if (old_query_id && num_formatted)
 
997
            (*num_formatted)++;
 
998
         alignments_count = num_alignments;
 
999
         /* New query: find the corresponding SeqLoc */
 
1000
         while (slp && SeqIdComp(query_id, SeqLocId(slp)) != SIC_YES)
 
1001
            slp = slp->next;
 
1002
         if (slp != NULL) {
 
1003
            query_id = old_query_id = SeqLocId(slp);
 
1004
            /* Print new query information */
 
1005
            if (print_query_info)
 
1006
               PrintTabularOutputHeader(NULL, NULL, slp, NULL, 0, 
 
1007
                                        believe_query, fp);
 
1008
         } else if (query_bsp)
 
1009
            old_query_id = query_bsp->id;
 
1010
         defline = (CharPtr) Malloc(BUFFER_LENGTH+1);
 
1011
         SeqIdWrite(query_id, defline, PRINTID_FASTA_LONG, BUFFER_LENGTH);
 
1012
         if (StringNCmp(defline, "lcl|", 4))
 
1013
            StringCpy(query_buffer, defline);
 
1014
         else if (!believe_query) {
 
1015
            if (slp) {
 
1016
               BioseqUnlock(query_bsp);
 
1017
               query_bsp = BioseqLockById(query_id);
 
1018
            }
 
1019
            if ((title = StringSave(BioseqGetTitle(query_bsp))) != NULL) {
 
1020
               defline = MemFree(defline);
 
1021
               defline = StringTokMT(title, " ", &title);
 
1022
               StringNCpy_0(query_buffer, defline, BUFFER_LENGTH);
 
1023
               defline = MemFree(defline);
 
1024
            } else
 
1025
               StringCpy(query_buffer, defline+4);
 
1026
            defline = MemFree(defline);
 
1027
         } else
 
1028
            StringCpy(query_buffer, defline+4);
 
1029
      } else
 
1030
         query_id = old_query_id;      
 
1031
 
 
1032
      subject_id = TxGetSubjectIdFromSeqAlign(sap);
 
1033
 
 
1034
      if (SeqIdComp(subject_id, old_subject_id) != SIC_YES) {
 
1035
         /* New subject sequence has been found in the seqalign list */
 
1036
         if (--alignments_count < 0)
 
1037
            continue;
 
1038
         BioseqUnlock(subject_bsp);
 
1039
         subject_bsp = BioseqLockById(subject_id);
 
1040
      
 
1041
         if (!subject_bsp || !subject_bsp->id)
 
1042
            continue;
 
1043
         if (subject_bsp->id->choice != SEQID_GENERAL ||
 
1044
             StringCmp(((DbtagPtr)subject_id->data.ptrvalue)->db, "BL_ORD_ID")) {
 
1045
            defline = (CharPtr) Malloc(BUFFER_LENGTH+1);
 
1046
            SeqIdWrite(subject_bsp->id, defline, PRINTID_FASTA_LONG, BUFFER_LENGTH);
 
1047
            if (StringNCmp(defline, "lcl|", 4))
 
1048
               StringCpy(subject_buffer, defline);
 
1049
            else
 
1050
               StringCpy(subject_buffer, defline+4);
 
1051
         } else {
 
1052
            defline = StringSave(BioseqGetTitle(subject_bsp));
 
1053
            defline = StringTokMT(defline, " \t", &title);
 
1054
            StringCpy(subject_buffer, defline);
 
1055
         }
 
1056
         defline = MemFree(defline);
 
1057
      }
 
1058
      
 
1059
      perc_ident = 0;
 
1060
      align_length = 0;
 
1061
      num_gap_opens = 0;
 
1062
      num_mismatches = 0;
 
1063
 
 
1064
      GetScoreAndEvalue(sap, &score, &bit_score, &evalue, &number);
 
1065
 
 
1066
      /* Do not allow knocking off digit in evalue buffer, so parsers are 
 
1067
         not confused. */
 
1068
      ScoreAndEvalueToBuffers(bit_score, evalue, 
 
1069
                              bit_score_buff, &eval_buff, 0);
 
1070
 
 
1071
      /* Loop on segments within this seqalign (in ungapped case) */
 
1072
      while (TRUE) {
 
1073
         if (sap->segtype == SAS_DENSEG) {
 
1074
            Boolean get_num_ident = TRUE;
 
1075
            dsp = (DenseSegPtr) sap->segs;
 
1076
            numseg = dsp->numseg;
 
1077
            /* Query Bioseq is needed for calculating number of identities.
 
1078
               NB: even if number of identities is already filled in the 
 
1079
               seqalign score list, that is not enough here, because we need to
 
1080
               know number of identities in each segment in order to calculate
 
1081
               number of mismatches correctly. */
 
1082
            if (!query_bsp) {
 
1083
               query_bsp = BioseqLockById(query_id);
 
1084
            }
 
1085
 
 
1086
            for (i=0; i<numseg; i++) {
 
1087
               align_length += dsp->lens[i];
 
1088
               if (dsp->starts[2*i] != -1 && dsp->starts[2*i+1] != -1) {
 
1089
                  if (get_num_ident) {
 
1090
                     num_ident = BlastBioseqGetNumIdentical(query_bsp, subject_bsp, 
 
1091
                                    dsp->starts[2*i], dsp->starts[2*i+1], 
 
1092
                                    dsp->lens[i], dsp->strands[2*i], 
 
1093
                                    dsp->strands[2*i+1]);
 
1094
                     perc_ident += num_ident;
 
1095
                     num_mismatches += dsp->lens[i] - num_ident;
 
1096
                  }
 
1097
               } else {
 
1098
                  num_gap_opens++;
 
1099
               }
 
1100
            }
 
1101
            perc_ident = perc_ident / align_length * 100;
 
1102
 
 
1103
            if (dsp->strands[0] != dsp->strands[1]) {
 
1104
               q_start = dsp->starts[2*numseg-2] + 1;
 
1105
               q_end = dsp->starts[0] + dsp->lens[0];
 
1106
               s_end = dsp->starts[1] + 1;
 
1107
               s_start = dsp->starts[2*numseg-1] + dsp->lens[numseg-1];
 
1108
            } else {
 
1109
               q_start = dsp->starts[0] + 1;
 
1110
               q_end = dsp->starts[2*numseg-2] + dsp->lens[numseg-1];
 
1111
               s_start = dsp->starts[1] + 1;
 
1112
               s_end = dsp->starts[2*numseg-1] + dsp->lens[numseg-1];
 
1113
            }
 
1114
         } else if (sap->segtype == SAS_STD) {
 
1115
            if (!ssp)
 
1116
               ssp = (StdSegPtr) sap->segs;
 
1117
            
 
1118
            if (is_ungapped) {
 
1119
               sap_tmp->segtype = SAS_STD;
 
1120
               sap_tmp->segs = ssp;
 
1121
               GetScoreAndEvalue(sap_tmp, &score, &bit_score, &evalue, &number);
 
1122
               ScoreAndEvalueToBuffers(bit_score, evalue, 
 
1123
                                       bit_score_buff, &eval_buff, 0);
 
1124
               find_score_in_align(sap_tmp, 1, asp);
 
1125
            } else
 
1126
               find_score_in_align(sap, 1, asp);
 
1127
            
 
1128
            if (asp->m_frame < 0)
 
1129
               q_start = SeqLocStop(ssp->loc) + 1;
 
1130
            else
 
1131
               q_start = SeqLocStart(ssp->loc) + 1;
 
1132
            
 
1133
            if (asp->t_frame < 0)
 
1134
               s_start = SeqLocStop(ssp->loc->next) + 1;
 
1135
            else
 
1136
               s_start = SeqLocStart(ssp->loc->next) + 1;
 
1137
            
 
1138
            if (!is_ungapped) {
 
1139
               for (index=1; ssp->next; index++)
 
1140
                  ssp = ssp->next;
 
1141
               num_gap_opens = index / 2;
 
1142
            } else 
 
1143
               num_gap_opens = 0;
 
1144
 
 
1145
            if (asp->m_frame < 0)
 
1146
               q_end = SeqLocStart(ssp->loc) + 1;
 
1147
            else
 
1148
               q_end = SeqLocStop(ssp->loc) + 1;
 
1149
            
 
1150
            if (asp->t_frame < 0)
 
1151
               s_end = SeqLocStart(ssp->loc->next) + 1;
 
1152
            else
 
1153
               s_end = SeqLocStop(ssp->loc->next) + 1;
 
1154
            
 
1155
            align_length = asp->totlen;
 
1156
            num_mismatches = asp->totlen - asp->gaps - asp->identical;
 
1157
            perc_ident = ((FloatHi) 100*asp->identical)/ (asp->totlen);
 
1158
         } else if (sap->segtype == SAS_DENDIAG) {
 
1159
            if (!ddp)
 
1160
               ddp = (DenseDiagPtr) sap->segs;
 
1161
            sap_tmp->segtype = SAS_DENDIAG;
 
1162
            sap_tmp->segs = ddp;
 
1163
            GetScoreAndEvalue(sap_tmp, &score, &bit_score, &evalue, &number);
 
1164
            ScoreAndEvalueToBuffers(bit_score, evalue, 
 
1165
                                    bit_score_buff, &eval_buff, 0);
 
1166
 
 
1167
            align_length = ddp->len;
 
1168
            if (ddp->strands[0] == Seq_strand_minus) {
 
1169
               q_start = ddp->starts[0] + align_length;
 
1170
               q_end = ddp->starts[0] + 1;
 
1171
            } else {
 
1172
               q_start = ddp->starts[0] + 1;
 
1173
               q_end = ddp->starts[0] + align_length;
 
1174
            }
 
1175
 
 
1176
            if (ddp->strands[1] == Seq_strand_minus) {
 
1177
               s_start = ddp->starts[1] + align_length;
 
1178
               s_end = ddp->starts[1] + 1;
 
1179
            } else {
 
1180
               s_start = ddp->starts[1] + 1;
 
1181
               s_end = ddp->starts[1] + align_length;
 
1182
            }
 
1183
            num_gap_opens = 0;
 
1184
            /* Query Bioseq is needed for calculating number of identities.
 
1185
               NB: even if number of identities is already filled in the 
 
1186
               seqalign score list, that is not enough here, because we need to
 
1187
               know number of identities in each segment in order to calculate
 
1188
               number of mismatches correctly. */
 
1189
            if (!query_bsp) {
 
1190
               query_bsp = BioseqLockById(query_id);
 
1191
            }
 
1192
 
 
1193
            num_ident = BlastBioseqGetNumIdentical(query_bsp, subject_bsp, 
 
1194
                           ddp->starts[0], ddp->starts[1], align_length, 
 
1195
                           ddp->strands[0], ddp->strands[1]);
 
1196
            num_mismatches = align_length - num_ident;
 
1197
            perc_ident = ((FloatHi)num_ident) / align_length * 100;
 
1198
         }
 
1199
         if (!is_translated) {
 
1200
            /* Adjust coordinates if query and/or subject is a subsequence */
 
1201
            q_start += q_shift;
 
1202
            q_end += q_shift;
 
1203
            s_start += s_shift;
 
1204
            s_end += s_shift;
 
1205
         }
 
1206
         
 
1207
         if (perc_ident >= 99.995 && perc_ident < 100.00)
 
1208
            perc_ident = 99.99;
 
1209
         
 
1210
         fprintf(fp, 
 
1211
                 "%s\t%s\t%.2f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s\t%s\n",
 
1212
                 query_buffer, subject_buffer, perc_ident, align_length, 
 
1213
                 num_mismatches, num_gap_opens, q_start, 
 
1214
                 q_end, s_start, s_end, eval_buff, bit_score_buff);
 
1215
         old_subject_id = subject_id;
 
1216
         if (sap->segtype == SAS_DENSEG)
 
1217
            break;
 
1218
         else if (sap->segtype == SAS_DENDIAG) {
 
1219
            if ((ddp = ddp->next) == NULL)
 
1220
               break;
 
1221
         } else if (sap->segtype == SAS_STD) {
 
1222
            if ((ssp = ssp->next) == NULL)
 
1223
               break;
 
1224
         }
 
1225
      }
 
1226
   }
 
1227
 
 
1228
   eval_buff = MemFree(eval_buff);
 
1229
 
 
1230
   if (is_ungapped)
 
1231
      sap_tmp = MemFree(sap_tmp);
 
1232
 
 
1233
   if (is_translated) {
 
1234
      free_default_matrix(asp->matrix);
 
1235
      MemFree(asp);
 
1236
   }
 
1237
 
 
1238
   BioseqUnlock(subject_bsp);
 
1239
   if (query_slp)
 
1240
      BioseqUnlock(query_bsp);
 
1241
}
 
1242
 
 
1243
 
 
1244
 
 
1245
/* Mutex for assignment of db seqs to search. */
 
1246
TNlmMutex err_message_mutex=NULL;
 
1247
 
 
1248
#define BLAST_ERROR_BULEN 50
 
1249
/*
 
1250
        The following functions fill a the Error user string with
 
1251
        text to identify BLAST and the entry being worked on.
 
1252
        The SeqIdPtr is used to make a FASTA id, which is appended
 
1253
        to string.
 
1254
 
 
1255
        A Uint1 is returned, which allows Nlm_ErrUserDelete to delete
 
1256
        this error string when it's done.
 
1257
*/
 
1258
 
 
1259
Uint1
 
1260
BlastSetUserErrorString(CharPtr string, SeqIdPtr sip, Boolean use_id)
 
1261
 
 
1262
{
 
1263
        BioseqPtr bsp;
 
1264
        Char buffer[2*BLAST_ERROR_BULEN+1], textid[BLAST_ERROR_BULEN+1];
 
1265
        CharPtr buf_start, ptr, title;
 
1266
        Int2 length=0, index;
 
1267
        Uint1 retval=0;
 
1268
 
 
1269
        buffer[0] = NULLB;
 
1270
        ptr = buf_start = &buffer[0];
 
1271
 
 
1272
        if (string)
 
1273
                StringNCpy_0(ptr, string, BLAST_ERROR_BULEN);
 
1274
 
 
1275
        if (sip != NULL)
 
1276
        {
 
1277
            bsp = BioseqLockById(sip);
 
1278
            if(bsp)
 
1279
            {
 
1280
                if (use_id)
 
1281
                        sip = bsp->id;
 
1282
                else
 
1283
                        title = BioseqGetTitle(bsp);
 
1284
            }
 
1285
 
 
1286
            if (string)
 
1287
            {
 
1288
                length = StringLen(string);
 
1289
                if (length > BLAST_ERROR_BULEN)
 
1290
                        length = BLAST_ERROR_BULEN;
 
1291
            }
 
1292
 
 
1293
            ptr += length;
 
1294
 
 
1295
            if (use_id)
 
1296
            {
 
1297
                SeqIdWrite(sip, textid, PRINTID_FASTA_LONG, BLAST_ERROR_BULEN-1);
 
1298
                StringNCpy_0(ptr, textid, BLAST_ERROR_BULEN-1);
 
1299
            }
 
1300
            else if (title)
 
1301
            {
 
1302
                for (index=0; index<BLAST_ERROR_BULEN-1; index++)
 
1303
                {
 
1304
                        if (title[index] == NULLB || title[index] == ' ')
 
1305
                        {
 
1306
                                break;
 
1307
                        }
 
1308
                        *ptr = title[index];
 
1309
                        ptr++;
 
1310
                }
 
1311
                *ptr = NULLB;
 
1312
            }
 
1313
            BioseqUnlock(bsp);
 
1314
            StringCpy(ptr+StringLen(ptr), ":");
 
1315
        }
 
1316
        NlmMutexLockEx(&err_message_mutex);
 
1317
        retval = Nlm_ErrUserInstall (buf_start, 0);
 
1318
        NlmMutexUnlock(err_message_mutex);
 
1319
 
 
1320
        return retval;
 
1321
}
 
1322
 
 
1323
void
 
1324
BlastDeleteUserErrorString(Uint1 err_id)
 
1325
 
 
1326
{
 
1327
        NlmMutexLockEx(&err_message_mutex);
 
1328
        Nlm_ErrUserDelete(err_id);
 
1329
        NlmMutexUnlock(err_message_mutex);
 
1330
        return;
 
1331
}
 
1332