diff options
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/asn2graphic.c | 2115 | ||||
-rw-r--r-- | desktop/asn2graphic.h | 12 | ||||
-rw-r--r-- | desktop/asn2graphicp.h | 13 | ||||
-rw-r--r-- | desktop/biosrc.c | 82 | ||||
-rw-r--r-- | desktop/bspview.c | 65 | ||||
-rw-r--r-- | desktop/bspview.h | 6 | ||||
-rw-r--r-- | desktop/cdrgn.c | 302 | ||||
-rw-r--r-- | desktop/cdrgn.h | 8 | ||||
-rw-r--r-- | desktop/dlgutil1.c | 17 | ||||
-rw-r--r-- | desktop/dlgutil2.c | 19 | ||||
-rw-r--r-- | desktop/dlogutil.h | 3 | ||||
-rw-r--r-- | desktop/dotvibrant.c | 9 | ||||
-rw-r--r-- | desktop/e2docsum.c | 134 | ||||
-rw-r--r-- | desktop/gbfview.c | 37 | ||||
-rw-r--r-- | desktop/gphview.c | 37 | ||||
-rw-r--r-- | desktop/import.c | 12 | ||||
-rw-r--r-- | desktop/salogif.c | 11 | ||||
-rw-r--r-- | desktop/salsa.c | 5 | ||||
-rw-r--r-- | desktop/seqpanel.c | 4 | ||||
-rw-r--r-- | desktop/seqsub.c | 66 | ||||
-rw-r--r-- | desktop/vsm.c | 5 |
21 files changed, 2523 insertions, 439 deletions
diff --git a/desktop/asn2graphic.c b/desktop/asn2graphic.c index 645c5f16..33427a5f 100644 --- a/desktop/asn2graphic.c +++ b/desktop/asn2graphic.c @@ -28,7 +28,7 @@ * * Version Creation Date: 11/8/01 * -* $Revision: 6.96 $ +* $Revision: 6.119 $ * * File Description: * @@ -45,6 +45,26 @@ #include <drawingp.h> #include <alignmgr2.h> +/* type used to accumulate align score weights, should be small to save space, but large enough we do not overflow. */ +typedef Uint2 AccumValue_t; +typedef AccumValue_t PNTR AccumValuePtr_t; +#define ACCUMVALUE_MAX UINT2_MAX + +/* + Given a sequence alignment, look at its score + and return a suitable integer (AccumValue_t) weight.' + scoretype gives which part of the score to use. +*/ +enum { + NLM_SCORE_COUNT = 0, + NLM_SCORE_SCORE, + NLM_SCORE_BIT, + NLM_SCORE_EVALUE, + NLM_SCORE_NUMBER, + NLM_SCORE_TOOBIG +}; + + #define RELEVANT_FEATS_PER_CHUNK 128 /* these do not apply to individual features; they are used, ie in "AddFeatureToFilter (FEATDEF_ANY_RNA. . .) @@ -89,6 +109,7 @@ typedef struct viewerInstanceData { Int4 from; Int4 to; Boolean allFeatures; + GraphicViewExtrasPtr extras; } ViewerContext, PNTR ViewerContextPtr; typedef struct featureFilterState { @@ -97,9 +118,25 @@ typedef struct featureFilterState { Uint2 indexInBlock; } FeatureFilterState, PNTR FeatureFilterStatePtr; +#define MAX_ALIGN_SORT_LABEL 20 +typedef struct seq_align_sort_info { + SeqAlignPtr sap; + Int4 start, stop; + Uint1 strand; + Char label[MAX_ALIGN_SORT_LABEL + 1]; + AccumValue_t normScore; +} SeqAlignSortInfo, PNTR SeqAlignSortInfoPtr; + typedef struct AlignmentFilterState { - SeqAlignPtr SAPhead, SAPcurrent; - Uint2 align; + /* SeqAlignPtr SAPhead, SAPcurrent; /* obsolete */ + SeqAlignSortInfoPtr alignSorted; /* array of SeqAlignPtrs & Info about them, sorted */ + Int4 alignSortedLen; /* len of alignSorted */ + Int4 alignIndex; /* index of current alignment in alignSorted */ + Uint1 scoreType; /* what kind of score will we filter and weight by? */ + Int2 cutoffPercent; /* include alignments in alignSorted only if their score is in the top cutoffPercent */ + AccumValue_t cutoffScore; /* normalised score Below which aligns won't get into alignSorted. */ + AccumValue_t cutoffScoreHi; /* normalised score Above which aligns won't get into alignSorted. */ + Int4 minScore, maxScore; /* un-normalised min & max scores seen on these alignments */ } AlignmentFilterState, PNTR AlignmentFilterStatePtr; /* @@ -173,6 +210,66 @@ static LayoutAlgorithm LayoutValues [] = { Layout_GroupCorrespondingFeatsRepeat }; +static CharPtr AlnScoreStrings [] = { + "None", + "Score", + "Bit Score", + "E-value", + "Number", + NULL +}; + +/* +static CharPtr AlnScoreCutoffStrings[] = { + "100%", + "50%", + "20%", + "10%", + "5%", + "2%", + "1%", + NULL +}; + +static Int2 AlnScoreCutoffValues [] = { + 100, + 50, + 20, + 10, + 5, + 2, + 1, + 0 +}; +*/ + + +static CharPtr AlnScoreCutoffStrings[] = { + "None", + "40", + "50", + "60", + "70", + "80", + "100", + "200", + "400", + NULL +}; + +static Int2 AlnScoreCutoffValues [] = { + -1, + 40, + 50, + 60, + 70, + 80, + 100, + 200, + 400, + 0 +}; + static CharPtr LlocStrings [] = { "none", "clip", @@ -339,6 +436,44 @@ static Uint1 ColorValues[][3] = { static Char config_filename [] = "asn2gph"; +/*** Static function declarations ****/ + +static Int4 PixelsBetweenSeqCoords(Int4 left, Int4 right, Uint4 viewScale); +static Boolean IsInsertTic(RelevantFeatureItemPtr RFIP); +static void render_insert_tics(RenderInputPtr RIP); + +/* functions for working with alignments */ +/* perhaps some of these should be moved to the alignment manager. */ +static Boolean SeqAlignContentLabel(SeqAlignPtr sap, SeqIdPtr notThisSID, CharPtr buf, Int4 buflen, Uint1 format); +AccumValue_t NormaliseScore(Int4 rawscore, Int4 min, Int4 max); +static Int4 WeightFromAlignScore(SeqAlignPtr sap, Uint1 scoreType); +static void FindCutoffScore(SeqAlignPtr sap, Int4 alignCnt, AlignmentFilterStatePtr afsp); +static void GatherAlignInfo( + SeqAlignPtr sap, + Int4 alignCnt, + SeqIdPtr bioSeqId, + AlignmentFilterStatePtr afsp +); +static Boolean AlignmentFilterStateInit(SeqAlignPtr sap, SeqIdPtr sid, AlignmentFilterStatePtr afsp, GraphicViewExtrasPtr extras); +static Boolean AlignmentFilterStateDone(AlignmentFilterStatePtr afsp); +static void AlignmentFilterStateFree( AlignmentFilterStatePtr afsp); + +typedef struct align_seg_iterator { + SeqAlignPtr sap; + SeqIdPtr sip; + + Int4 nsegs; + Int4 start, stop; /* left and rightmost bioseq coords for this alignment. */ + Uint1 strand; /* so we iterate the right direction */ + Int4 alignRow; /* from sip on non-stdseg aligns */ + Int4 currentSeg; /* for indexed aligns */ + StdSegPtr currentStdSeg; /* for std seg aligns */ +} AlignSegIterator, PNTR AlignSegIteratorPtr; + +static Int4 AlignSegIteratorCreate(SeqAlignPtr sap, SeqIdPtr sip, AlignSegIteratorPtr asi); +static Boolean AlignSegIteratorNext(AlignSegIteratorPtr asip, Int4Ptr start, Int4Ptr stop, Uint1Ptr strand, Uint1Ptr segType); + + static Int1 StringIndexInStringList (CharPtr testString, CharPtr PNTR stringList) { Int1 i; @@ -503,7 +638,7 @@ NLM_EXTERN LayoutAlgorithm FindLayoutByName ( { Int1 i; - if (StringHasNoText (name)) return 0; + if (StringHasNoText (name)) return Layout_Inherit; i = StringIndexInStringList (name, LayoutStrings); if (i >= 0 && i < DIM (LayoutValues)) { return LayoutValues [i]; @@ -1733,6 +1868,23 @@ static void getDim_render_with_line ( *height = 1; } +static void render_wrap_around_markers( + RenderInputPtr RIP, + ViewerContextPtr vContext +) +{ + Uint4 StartY; + RelevantFeatureItemPtr RFIP; + AppearanceItemPtr AIP; + + RFIP = RIP->RFIP; + AIP = RIP->AIP; + StartY = RIP->yStart - (RIP->featureOffset) - AIP->Height / 2 - 1; + + AddSymbol(RIP->drawSeg, RFIP->Left - 3 * vContext->viewScale, StartY, LEFT_TRIANGLE_SYMBOL, FALSE, MIDDLE_LEFT, 0); + AddSymbol(RIP->drawSeg, RFIP->Right + 3 * vContext->viewScale, StartY, RIGHT_TRIANGLE_SYMBOL, FALSE, MIDDLE_RIGHT, 0); +} + static void render_with_line ( RenderInputPtr RIP, ViewerContextPtr vContext @@ -1757,8 +1909,21 @@ static void render_with_line ( stop = MAX (RFIP->Right, vContext->to); } - thisPrim = AddLine (RIP->drawSeg, start, StartY, stop, StartY, 0, 0); + if (!RFIP->circularSpanningOrigin || RFIP->numivals < 2) { + thisPrim = AddLine (RIP->drawSeg, start, StartY, stop, StartY, 0, 0); SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } else { + /* feature spans the origin. draw specially */ + if (RFIP->ivals[0] < stop) { + thisPrim = AddLine (RIP->drawSeg, RFIP->ivals[0], StartY, stop, StartY, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } + if (RFIP->ivals[2* RFIP->numivals - 1] > start) { + thisPrim = AddLine (RIP->drawSeg, start, StartY, RFIP->ivals[2* RFIP->numivals - 1], StartY, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } + render_wrap_around_markers(RIP, vContext); + } } static void getDim_render_with_capped_line ( @@ -1802,10 +1967,20 @@ static void render_with_capped_line ( render_with_line (RIP, vContext); RFIP = RIP->RFIP; AIP = RIP->AIP; - thisPrim = AddLine (RIP->drawSeg, RFIP->Left, StartY, RFIP->Left, StartY - AIP->Height, 0, 0); - SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); - thisPrim = AddLine (RIP->drawSeg, RFIP->Right, StartY, RFIP->Right, StartY - AIP->Height, 0, 0); - SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + + + if (!RFIP->circularSpanningOrigin || RFIP->numivals < 2) { + thisPrim = AddLine (RIP->drawSeg, RFIP->Left, StartY, RFIP->Left, StartY - AIP->Height, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + thisPrim = AddLine (RIP->drawSeg, RFIP->Right, StartY, RFIP->Right, StartY - AIP->Height, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } else { + /* origin spanning feature */ + thisPrim = AddLine (RIP->drawSeg, RFIP->ivals[0], StartY, RFIP->ivals[0], StartY - AIP->Height, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + thisPrim = AddLine (RIP->drawSeg, RFIP->ivals[2* RFIP->numivals - 1], StartY, RFIP->ivals[2* RFIP->numivals - 1], StartY - AIP->Height, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } } static void getDim_render_with_box ( @@ -1815,7 +1990,6 @@ static void getDim_render_with_box ( Uint2Ptr height, ViewerContextPtr vContext ) - { RelevantFeatureItemPtr RFIP; AppearanceItemPtr AIP; @@ -1825,66 +1999,75 @@ static void getDim_render_with_box ( *Start = RFIP->Left; *Stop = RFIP->Right; *height = AIP->Height; + if (IsInsertTic(RFIP)) + *height += AIP->Height; } +static Boolean IsInsertTic(RelevantFeatureItemPtr RFIP) +{ + int iival; + + /* Insert Tics only on alignments with more than one segment */ + if (RFIP->featdeftype != APPEARANCEITEM_Alignment || RFIP->numivals < 2) + return FALSE; + + for (iival = 0; iival < RFIP->numivals; ++iival) { + /* a segment with beginning and end the same is an insert */ + if (RFIP->ivals [2 * iival] == RFIP->ivals [2 * iival + 1] ) { + return TRUE; + } + } + return FALSE; +} + +#if 0 /* TestForSmearOverlap was replaced by PixelsBetweenSeqCoords everwhere it was used */ static Boolean TestForSmearOverlap ( Int4 PrevEnd, Int4 NewStart, ViewerContextPtr vContext ) - { - Int4 PrevPixelStart; - /* base-pair coordinates of the beginning of the last occupied pixel*/ - PrevPixelStart = PrevEnd - PrevEnd % vContext->viewScale; - if (PrevPixelStart + vContext->viewScale > NewStart) return TRUE; - return FALSE; + return PixelsBetweenSeqCoords(PrevEnd, NewStart, vContext->viewScale) < 1; } +#endif -static Boolean TestForVisibleGap ( +/* returns TRUE if no visible gap. */ +static Boolean NoVisibleGap ( Int4 x1, Int4 x2, - ViewerContextPtr vContext + Uint4 viewScale ) - { - Int4 xmin, xmax; - - if (x1 == x2) return FALSE; - if (x1 > x2) { - xmin = x2; - xmax = x1; - } else { - xmin = x1; - xmax = x2; - } - - xmin -= xmin % vContext->viewScale; /* xmin is now the _beginning_ of the pixel it occupies in _base pair_ coordinates (I hope) */ - if (abs (xmax - xmin) < 2 * vContext->viewScale) return TRUE; - return FALSE; + return abs(PixelsBetweenSeqCoords(x1, x2, viewScale)) < 2; } static Boolean TestForSmear ( RelevantFeatureItemPtr RFIP1, RelevantFeatureItemPtr RFIP2, - ViewerContextPtr vContext + Uint4 viewScale ) - { Uint4 minSeperation; + + minSeperation = 5; /* do not smear a feature more than 5 pixels wide */ - minSeperation = 5 * vContext->viewScale; /* do not smear a feature more than 5 pixels wide */ - - if (abs (RFIP1->Right - RFIP1->Left) >= minSeperation) return FALSE; - if (abs (RFIP2->Right - RFIP2->Left) >= minSeperation) return FALSE; + if (abs(PixelsBetweenSeqCoords(RFIP1->Right, RFIP1->Left, viewScale)) >= minSeperation) return FALSE; + if (abs(PixelsBetweenSeqCoords(RFIP2->Right, RFIP2->Left, viewScale)) >= minSeperation) return FALSE; - return (TestForVisibleGap (RFIP1->Right, RFIP2->Left, vContext) - || TestForVisibleGap (RFIP1->Right, RFIP2->Right, vContext) - || TestForVisibleGap (RFIP1->Left, RFIP2->Right, vContext) - || TestForVisibleGap (RFIP1->Left, RFIP2->Left, vContext) ); + return (NoVisibleGap (RFIP1->Right, RFIP2->Left, viewScale) + || NoVisibleGap (RFIP1->Right, RFIP2->Right, viewScale) + || NoVisibleGap (RFIP1->Left, RFIP2->Right, viewScale) + || NoVisibleGap (RFIP1->Left, RFIP2->Left, viewScale) ); } +static Int4 PixelsBetweenSeqCoords(Int4 left, Int4 right, Uint4 viewScale) +{ + /* Will be negative if right is really not right of left. */ + /* 0 if they fall on the same pixel. */ + /* Do NOT change this to (right - left)/viewScale. NOT the same. */ + return (right/viewScale - left/viewScale); +} static void render_with_box_master ( RenderInputPtr RIP, @@ -1930,15 +2113,15 @@ static void render_with_box_master ( } else { /* nope */ arrow = NO_ARROW; - if (RFIP->plusstrand) { + if (RFIP->featstrand == Seq_strand_plus) { arrow = RIGHT_ARROW; - } else { + } else if (RFIP->featstrand == Seq_strand_minus) { arrow = LEFT_ARROW; } if (! AIP->ShowArrow) { arrow = NO_ARROW; } - if (ABS (RFIP->Right - RFIP->Left) / vContext->viewScale < AP->MinPixelsForArrow) { + if (abs(PixelsBetweenSeqCoords( RFIP->Left, RFIP->Right, vContext->viewScale)) < AP->MinPixelsForArrow) { arrow = NO_ARROW; } if (vContext->viewScale > AP->MaxScaleForArrow) { @@ -1954,31 +2137,68 @@ static void render_with_box_master ( /* collect a group of interval(s) which do not contain any pixels between them */ pieceIValStart = i; /* this tests is the i-plus-1th feature is part of the smear, which goes from pieceIValStart to i, inclusive */ - while (i + 1 < RFIP->numivals && - TestForVisibleGap (vContext->viewScale + RFIP->ivals [2 * i + 1], RFIP->ivals [2 * i + 2], vContext)) { - i++; + /* On alignments only smear away the gaps caused by inserts. */ + if (RFIP->featdeftype == APPEARANCEITEM_Alignment) { + while (i + 1 < RFIP->numivals && + NoVisibleGap (RFIP->ivals [2 * i + 1], RFIP->ivals [2 * i + 2], vContext->viewScale) && + (RFIP->ivals [2 * i] == RFIP->ivals [2 * i + 1] || RFIP->ivals [2 * i + 2] == RFIP->ivals [2 * i + 3])) { + i++; + } + } else { + while (i + 1 < RFIP->numivals && + NoVisibleGap (RFIP->ivals [2 * i + 1], RFIP->ivals [2 * i + 2], vContext->viewScale)) { + i++; + } } /* draw the segment and the gap -- drawing the gap first, so that it is overdrawn by the segment */ if (i + 1 < RFIP->numivals) { /* a gap is present if there are more ivals to consider after i*/ - if (AIP->GapChoice == LineGap) { - thisPrim = AddLine (RIP->drawSeg, RFIP->ivals [2 * i + 1], StartY - AIP->Height / 2, RFIP->ivals [2 * i + 2], StartY - AIP->Height / 2, 0, 0); - SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); - } else if (AIP->GapChoice == AngleGap) { - mid = (RFIP->ivals [2 * i + 2] + RFIP->ivals [2 * i + 1]) / 2; - thisPrim = AddLine (RIP->drawSeg, RFIP->ivals [2 * i + 1], StartY - AIP->Height / 2, mid, StartY, 0, 0); - SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); - thisPrim = AddLine (RIP->drawSeg, mid, StartY, RFIP->ivals [2 * i + 2], StartY - AIP->Height / 2, 0, 0); - SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + if (RFIP->circularSpanningOrigin && RFIP->ivals [2 * i + 1] > RFIP->ivals [2 * i + 2]) { + /* on a circular bioseq, this gap spans the origin and has to be drawn specially */ + /* RFIP->Left will be 0, RFIP->Right will be the length of the Bioseq */ + if (RFIP->ivals [2 * i + 1] < RFIP->Right - 1) { + /* Draw the part of the gap at the right end. Might not be any. */ + thisPrim = AddLine (RIP->drawSeg, RFIP->ivals[2 * i + 1], StartY - AIP->Height / 2, RFIP->Right, StartY - AIP->Height / 2, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } + if (RFIP->Left < RFIP->ivals [2 * i + 2]) { + /* draw the part of the gap at the left end. */ + thisPrim = AddLine (RIP->drawSeg, RFIP->Left, StartY - AIP->Height / 2, RFIP->ivals[2 * i + 2], StartY - AIP->Height / 2, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } + /* No. I didn't put in code to make those lines 'Angle Gap' style. Figured it wouldn't show up very well. You can if you want. */ + + /* draw markers to show that this wraps around */ + render_wrap_around_markers(RIP, vContext); + + } else { + /* ordinary gap */ + if (AIP->GapChoice == LineGap) { + thisPrim = AddLine (RIP->drawSeg, RFIP->ivals [2 * i + 1], StartY - AIP->Height / 2, + RFIP->ivals [2 * i + 2] - vContext->viewScale, StartY - AIP->Height / 2, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } else if (AIP->GapChoice == AngleGap) { + mid = (RFIP->ivals [2 * i + 2] + RFIP->ivals [2 * i + 1]) / 2; + thisPrim = AddLine (RIP->drawSeg, RFIP->ivals [2 * i + 1], StartY - AIP->Height / 2, + mid, StartY, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + thisPrim = AddLine (RIP->drawSeg, mid, StartY, + RFIP->ivals [2 * i + 2] - vContext->viewScale, StartY - AIP->Height / 2, 0, 0); + SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } } } arrow = NO_ARROW; - if (i == RFIP->numivals - 1) { - if (RFIP->plusstrand) { - arrow = RIGHT_ARROW; - } else { + if (i == RFIP->numivals - 1 && RFIP->featstrand == Seq_strand_plus) { + arrow = RIGHT_ARROW; + } else if (RFIP->featstrand == Seq_strand_minus) { + /* on minus strands, Alignments put their intervals in coordinate order. + Other features put theirs in biological order (right to left), + so we have to draw the arrow differently (or we could sort the intervals so they + ended up the same. */ + if ((pieceIValStart == 0 && RFIP->featdeftype == APPEARANCEITEM_Alignment) || + (i == RFIP->numivals - 1 && RFIP->featdeftype != APPEARANCEITEM_Alignment)) arrow = LEFT_ARROW; - } } if (! AIP->ShowArrow) { arrow = NO_ARROW; @@ -1993,9 +2213,38 @@ static void render_with_box_master ( SetPrimitiveIDs (thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); i++; } + if (RFIP->featdeftype == APPEARANCEITEM_Alignment) { + render_insert_tics(RIP); + } + } +} + + +static void render_insert_tics(RenderInputPtr RIP) +{ + AppearanceItemPtr AIP; + RelevantFeatureItemPtr RFIP; + PrimitivE thisPrim; + Int4 StartY; + Int4 i; + + RFIP = RIP->RFIP; + AIP = RIP->AIP; + StartY = RIP->yStart - (RIP->featureOffset); + + /* if we are drawing an aligment, and the interval is zero length, It is an insert. + Draw a vertical line the height of the bar under the bar to show this. */ + for (i = 0; i < RFIP->numivals; ++i) { + /* a segment with beginning and end the same is an insert */ + if (RFIP->ivals [2 * i] == RFIP->ivals [2 * i + 1] ) { + thisPrim = AddLine(RIP->drawSeg, RFIP->ivals [2 * i], StartY - AIP->Height, + RFIP->ivals [2 * i], StartY - AIP->Height * 2, FALSE, 0); + SetPrimitiveIDs(thisPrim, RFIP->entityID, RFIP->itemID, RFIP->itemType, 0); + } } } + static void render_with_box ( RenderInputPtr RIP, ViewerContextPtr vContext @@ -2558,9 +2807,11 @@ static Boolean GetAndCountFeatures ( rFeats [i].itemType = OBJ_SEQFEAT; rFeats [i].numivals = fContext.numivals; rFeats [i].ivals = fContext.ivals; - rFeats [i].plusstrand = (Boolean) (fContext.strand != Seq_strand_minus); + rFeats [i].featstrand = fContext.strand; + rFeats [i].circularSpanningOrigin = FALSE; if (rFeats [i].Left < 0 && fContext.bsp != NULL) { /* !!! for features that span origin JK !!! */ + rFeats [i].circularSpanningOrigin = TRUE; rFeats [i].Left = 0; rFeats [i].Right = fContext.bsp->length; } @@ -2570,6 +2821,20 @@ static Boolean GetAndCountFeatures ( rFeats [i].Right = rFeats [i].Left; rFeats [i].Left = swap; } + /* with trans-spliced genes the left and right values might not span all the intervals. */ + /* we will fix that */ + { + int ivali; + Int4 val; + for (ivali = 0; ivali < rFeats [i].numivals; ++ivali) { + val = rFeats[i].ivals[2*ivali]; + rFeats[i].Left = MIN( rFeats[i].Left, val ); + rFeats[i].Right = MAX( rFeats[i].Right, val ); + val = rFeats[i].ivals[2*ivali+1]; + rFeats[i].Left = MIN( rFeats[i].Left, val ); + rFeats[i].Right = MAX( rFeats[i].Right, val ); + } + } if (GetSeqAnnotName(fContext.sap)) { /* save this feature's Annot Ptr if it is a named Seq Annot. */ rFeats [i].sap = fContext.sap; } @@ -2657,7 +2922,7 @@ static Boolean EnsureFeatureHasSegment ( except for the one in 'notthisRow' which ordinarly will be the bioseq. */ -static Boolean SeqAlignContentLabel(SeqAlignPtr sap, Int4 notThisRow, CharPtr buf, Int4 buflen, Uint1 format) +static Boolean SeqAlignContentLabel(SeqAlignPtr sap, SeqIdPtr notThisSID, CharPtr buf, Int4 buflen, Uint1 format) { Int4 r, rows, slen; Char localbuf[100]; @@ -2676,13 +2941,14 @@ static Boolean SeqAlignContentLabel(SeqAlignPtr sap, Int4 notThisRow, CharPtr bu for (r = 1; r <= rows; ++r) { - if (r == notThisRow) - continue; sid = AlnMgr2GetNthSeqIdPtr(sap, r); if (sid == NULL) { sid = AlnMgr2GetNthSeqIdPtrStdSeg(sap, r); } - if (sid == NULL) return FALSE; + if (sid == NULL) + continue; + if (SeqIdIn(sid, notThisSID)) + continue; SeqIdWrite (sid, localbuf, format, sizeof (localbuf) - 1); slen = StringLen(localbuf); @@ -2691,8 +2957,8 @@ static Boolean SeqAlignContentLabel(SeqAlignPtr sap, Int4 notThisRow, CharPtr bu if (!firstTime) { StringNCat(buf, rowDelim, buflen); buflen -= sizeof(rowDelim) - 1; - firstTime = FALSE; } + firstTime = FALSE; StringNCat(buf, localbuf, buflen); buflen -= slen + 1; } @@ -2703,120 +2969,470 @@ static Boolean SeqAlignContentLabel(SeqAlignPtr sap, Int4 notThisRow, CharPtr bu return TRUE; } +#define _DEBUG + +static void AccumIvals(Int1* accumulator, Int4 accumBegin, Int4 accumLen, RelevantFeatureItemPtr RFIP); +Int4 CountIvals(Int1* accumulator, Int4 accumLen); +void MakeIvals(Int1* accumulator, Int4 accumBegin, Int4 accumLen, Int4Ptr ivalsOut, Int4 ivalsLen); + static RelevantFeatureItemPtr GetNextRFIPinAlignmentFilter ( FilterProcessStatePtr FPSP ) { - AlignmentFilterStatePtr alignSP; - SeqAlignPtr SAlnP; - Int4 alignRow, start, stop; - Int4 alignStart, alignStop; - Int4 nsegs, iseg, i; - Int4 row2, seq2Start; - SeqIdPtr SID; - BioseqPtr BSP; - RelevantFeatureItemPtr RFIP; - ViewerContextPtr vContext; - FilterItemPtr currentFIP; - Boolean stdSeg = FALSE; - AppearanceItemPtr AIP; - Char labelbuf[150]; + AlignmentFilterStatePtr alignSP; + SeqAlignSortInfoPtr alignSorted; + SeqAlignPtr SAlnP; + Int4 start, stop; + Uint1 segType; + Int4 nsegs, i; + SeqIdPtr SID; + BioseqPtr BSP; + RelevantFeatureItem RFI; /* holder for intermediate values we will merge together */ + RelevantFeatureItemPtr finalRFIP; /* Our return value. */ + ViewerContextPtr vContext; + FilterItemPtr currentFIP; + Boolean stdSeg = FALSE; + AppearanceItemPtr AIP; + Char labelbuf[150]; + Uint1 strand; + AlignSegIterator asi; + + if (FPSP == NULL) return NULL; + vContext = FPSP->vContext; + currentFIP = FPSP->currentFIP; + if (vContext == NULL || currentFIP == NULL) return NULL; - if (FPSP == NULL) return NULL; - vContext = FPSP->vContext; - currentFIP = FPSP->currentFIP; - if (vContext == NULL || currentFIP == NULL) return NULL; + BSP = vContext->BSP; + SID = BSP->id; + AIP = vContext->AppPtr->FeaturesAppearanceItem[APPEARANCEITEM_Alignment]; - AIP = vContext->AppPtr->FeaturesAppearanceItem[APPEARANCEITEM_Alignment]; + + alignSP = &FPSP->state.align; + alignSorted = alignSP->alignSorted; - alignSP = &FPSP->state.align; + SAlnP = alignSorted[alignSP->alignIndex].sap; - if (alignSP->SAPcurrent == NULL) return NULL; - SAlnP = alignSP->SAPcurrent; - alignSP->SAPcurrent = alignSP->SAPcurrent->next; - RFIP = MemNew (sizeof (RelevantFeatureItem)); - if (RFIP == NULL || (ValNodeAddPointer (&FPSP->needFreeList, 0, RFIP)) == NULL) { - MemFree (RFIP); - return NULL; + /* create new RFIP based on this SeqAlignPtr */ + finalRFIP = MemNew (sizeof (RelevantFeatureItem)); + if (finalRFIP == NULL || (ValNodeAddPointer (&FPSP->needFreeList, 0, finalRFIP)) == NULL) { + MemFree (finalRFIP); + return NULL; + } + + /* where does this alignment start & stop in bioseq coords? */ + nsegs = AlignSegIteratorCreate(SAlnP, SID, &asi); + strand = asi.strand; + if (strand == Seq_strand_unknown) + strand = Seq_strand_plus; + + if (asi.start < 0 || asi.stop < 0) + return NULL; + finalRFIP->Left = asi.start; + finalRFIP->Right = asi.stop; + finalRFIP->featstrand = strand; + finalRFIP->numivals = 1; + finalRFIP->ivals = NULL; + finalRFIP->featdeftype = APPEARANCEITEM_Alignment; + finalRFIP->circularSpanningOrigin = FALSE; + finalRFIP->entityID = SAlnP->idx.entityID; + finalRFIP->itemID = SAlnP->idx.itemID; + finalRFIP->itemType = SAlnP->idx.itemtype; + labelbuf[0] = 0; + if (SeqAlignContentLabel(SAlnP, SID, labelbuf, sizeof(labelbuf) - 1, AIP->format)) + { + finalRFIP->ContentLabel = StringSave(labelbuf); + } + + if (nsegs > 1) { + finalRFIP->ivals = MemNew (2 * nsegs * sizeof (Int4)); + if (finalRFIP->ivals == NULL) + { + MemFree(finalRFIP->ContentLabel); + return NULL; + } else { + finalRFIP->numivals = 0; + i = 0; + while (AlignSegIteratorNext(&asi, &start, &stop, NULL, &segType)) + { + /* ignore gaps on the bioseq */ + /* hence we may have less than nsegs ivals */ + if (segType == AM_GAP) + continue; + + if (segType == AM_INSERT) { + if (i == 0) + start = stop = finalRFIP->Left; + else + start = stop = finalRFIP->ivals[i - 1]; + } + finalRFIP->ivals[i++] = start; + finalRFIP->ivals[i++] = stop; + finalRFIP->numivals++; + } + } + } + + ++alignSP->alignIndex; + /* + if we are not done with all the alignments and + the next alignment(s) has the same accession and strand as this one does + merge their segments together. + */ + if (! AlignmentFilterStateDone(alignSP) && + alignSorted[alignSP->alignIndex - 1].strand == alignSorted[alignSP->alignIndex].strand && + StrNCmp(alignSorted[alignSP->alignIndex - 1].label, + alignSorted[alignSP->alignIndex].label, MAX_ALIGN_SORT_LABEL) == 0) { + Int4 *newIvals; /* pointer to merged ivals */ + Int4 newIvalsNum; + Int1 *accumulator; + Int4 accumBegin, accumEnd, accumLen; + + /* keep track of where the segments fall in this array */ + /* 0 - a gap. 1 - a segment. 2 - an insert */ + accumBegin = finalRFIP->Left; + accumEnd = vContext->seqLength; + accumLen = accumEnd - accumBegin; + accumulator = MemNew( accumLen * sizeof(Int1) ); + if (accumulator == NULL) { + return NULL; + } + + AccumIvals(accumulator, accumBegin, accumLen, finalRFIP); + for ( ; + ! AlignmentFilterStateDone(alignSP) && + alignSorted[alignSP->alignIndex - 1].strand == alignSorted[alignSP->alignIndex].strand && + StrNCmp(alignSorted[alignSP->alignIndex - 1].label, + alignSorted[alignSP->alignIndex].label, MAX_ALIGN_SORT_LABEL) == 0; + ++alignSP->alignIndex ) { + + SAlnP = alignSorted[alignSP->alignIndex].sap; + + /* where does this alignment start & stop in bioseq coords? */ + nsegs = AlignSegIteratorCreate(SAlnP, SID, &asi); + + if (asi.start < 0 || asi.stop < 0) + continue; + RFI.Left = asi.start; + finalRFIP->Left = MIN(finalRFIP->Left, RFI.Left); + RFI.Right = asi.stop; + finalRFIP->Right = MAX(finalRFIP->Right, RFI.Right); + RFI.numivals = 1; + RFI.ivals = NULL; + +#ifdef _DEBUG + if (finalRFIP->Right > vContext->seqLength) { + printf("finalRFIP->Right too big: %d\n", finalRFIP->Right); /* put a breakpoint here! */ + return NULL; + } +#endif + + if (nsegs > 1) { + RFI.ivals = MemNew (2 * nsegs * sizeof (Int4)); + if (RFI.ivals == NULL) + { + MemFree(RFI.ivals); + } else { + RFI.numivals = 0; + i = 0; + while (AlignSegIteratorNext(&asi, &start, &stop, NULL, &segType)) + { + /* ignore gaps on the bioseq */ + /* hence we may have less than nsegs ivals */ + if (segType == AM_GAP) + continue; + + if (segType == AM_INSERT) { + if (i == 0) + start = stop = RFI.Left; + else + start = stop = RFI.ivals[i - 1]; + } + RFI.ivals[i++] = start; + RFI.ivals[i++] = stop; + RFI.numivals++; + } + } + } + AccumIvals(accumulator, accumBegin, accumLen, &RFI); + if (RFI.ivals != NULL) + MemFree(RFI.ivals); + } + newIvalsNum = CountIvals(accumulator, accumLen); + newIvals = MemNew( 2 * newIvalsNum * sizeof(Int4) ); + if (newIvals == NULL) { + MemFree(accumulator); + return NULL; + } + MakeIvals(accumulator, accumBegin, accumLen, newIvals, newIvalsNum); + MemFree(accumulator); + + if (finalRFIP->ivals != NULL) + MemFree(finalRFIP->ivals); + finalRFIP->numivals = newIvalsNum; + + if (newIvalsNum > 1) { + finalRFIP->ivals = newIvals; + } else { + MemFree(newIvals); + finalRFIP->ivals = NULL; + } + } + + /* remember to delete the final ivals array & label space */ + if (finalRFIP->numivals > 1 && ValNodeAddPointer(&FPSP->needFreeList, 0, finalRFIP->ivals) == NULL) + { + MemFree(finalRFIP->ContentLabel); + MemFree(finalRFIP->ivals); + return NULL; + } + if (ValNodeAddPointer(&FPSP->needFreeList, 0, finalRFIP->ContentLabel) == NULL) + { + MemFree(finalRFIP->ContentLabel); + return NULL; + } + + return finalRFIP; +} + + +void AccumIvals(Int1* accumulator, Int4 accumBegin, Int4 accumLen, RelevantFeatureItemPtr RFIP) +{ + Int4 i, ai; + Int4 blockstart, blockend; + + /* mark everywhere segments spans. 0 in gaps, 1 in blocks, 2 at inserts */ + if (RFIP->numivals == 1) { + blockstart = RFIP->Left - accumBegin; + blockend = RFIP->Right - accumBegin; + + for (ai = blockstart; ai <= blockend; ++ai) + if (accumulator[ai] == 0) + accumulator[ai] = 1; + } + else { + for (i = 0; i < RFIP->numivals; ++i) { + blockstart = RFIP->ivals[2*i] - accumBegin; + blockend = RFIP->ivals[2*i + 1] - accumBegin; + +#ifdef _DEBUG + if (blockstart < 0 || accumLen < blockstart || blockend < 0 || accumLen < blockend) { + printf("AccumIvals problem!"); /* put a breakpoint here! */ + return; + } +#endif + if (blockstart == blockend) { + accumulator[blockstart] = 2; + } else { + for (ai = blockstart; ai <= blockend; ++ai) + if (accumulator[ai] == 0) + accumulator[ai] = 1; + } + } + } +} + +Int4 CountIvals(Int1* accumulator, Int4 accumLen) +{ + Int4 numivalsOut; + Int4 ai; + + /* make new ivals */ + numivalsOut = 0; + + for (ai = 0; ai < accumLen; ++ai) { + if (accumulator[ai] == 0) + continue; + /* if it is an insert, add it */ + if (accumulator[ai] == 2) { + ++numivalsOut; + } else if (accumulator[ai] == 1) { /* beginning of a block */ + /* find end of block */ + for (; ai < accumLen; ++ai) { + if (accumulator[ai] != 1) + break; + } + --ai; + ++numivalsOut; + } + } + return numivalsOut; +} + +void MakeIvals(Int1* accumulator, Int4 accumBegin, Int4 accumLen, Int4Ptr ivalsOut, Int4 ivalsLen) +{ + Int4 numivalsOut; + Int4 ai, blocklen; + + /* make new ivals */ + numivalsOut = 0; + + for (ai = 0; ai < accumLen && numivalsOut < ivalsLen; ++ai) { + /* ignore spots in gaps. */ + if (accumulator[ai] == 0) + continue; + /* if it is an insert, add it */ + if (accumulator[ai] == 2) { + ivalsOut[numivalsOut * 2] = accumBegin + ai; + ivalsOut[numivalsOut * 2 + 1] = accumBegin + ai; + ++numivalsOut; + } else if (accumulator[ai] == 1) { /* beginning of a block */ + /* find end of block */ + for (blocklen = 0; ai + blocklen < accumLen; ++blocklen) { + if (accumulator[ai + blocklen] != 1) + break; + } + ivalsOut[numivalsOut * 2] = accumBegin + ai; + if (accumulator[ai + blocklen] == 2) + ivalsOut[numivalsOut * 2 + 1] = accumBegin + ai + blocklen; + else + ivalsOut[numivalsOut * 2 + 1] = accumBegin + ai + blocklen - 1; + ++numivalsOut; + ai += blocklen - 1; + } + } +} + +/* + For a given SeqAlign and a given SeqId for a Seq that participates in that SeqAlign, + keep track of where we are in that alignment so we can iterate through all of that + alignment's segments, returning information about each segment. + Hides the differences between normal/indexable and StdSeg alignments. +*/ + +/* + Create an structure to iterate through all of an alignment's segments. + return a pointer to that iterator struct that must be deallocated. + return the number of segments. +*/ +static Int4 AlignSegIteratorCreate(SeqAlignPtr sap, SeqIdPtr sip, AlignSegIteratorPtr asip) +{ + Boolean stdSeg; + Int4 swap; + + if (sap == NULL || sip == NULL || asip == NULL) + return 0; + + AlnMgr2IndexSingleChildSeqAlign(sap); + asip->sap = sap; + asip->sip = sip; + + stdSeg = (sap->segtype == SAS_STD); + if ( ! stdSeg) { + asip->nsegs = AlnMgr2GetNumSegs(sap); + asip->alignRow = AlnMgr2GetFirstNForSipList (sap, sip); + if (asip->alignRow == -1) { + return 0; + } + AlnMgr2GetNthSeqRangeInSA(sap, asip->alignRow, &asip->start, &asip->stop); + asip->strand = AlnMgr2GetNthStrand(sap, asip->alignRow); } - /* make sure the alignment is indexed */ - if (!AlnMgr2IndexSingleChildSeqAlign (SAlnP)) return NULL; - BSP = vContext->BSP; - SID = BSP->id; - /* which row in the alignment is the BioSeq? */ - alignRow = AlnMgr2GetFirstNForSip (SAlnP, SID); - if (alignRow == -1) - { - alignRow = AlignMgr2GetFirstNForStdSeg (SAlnP, SID); - if (alignRow == -1) return NULL; - stdSeg = TRUE; + else { + asip->nsegs = AlnMgr2GetNumStdSegs(sap); + asip->alignRow = 0; + AlnMgr2GetSeqRangeForSipInSAStdSeg(sap, sip, &asip->start, &asip->stop, &asip->strand); } - - /* where does this alignment start & stop in bioseq coords? */ - if (!stdSeg) - AlnMgr2GetNthSeqRangeInSA (SAlnP, alignRow, &start, &stop); - else - AlnMgr2GetNthSeqRangeInSAStdSeg (SAlnP, alignRow, &start, &stop); - if (start < 0 || stop < 0) return NULL; - RFIP->Left = MIN (start, stop); - RFIP->Right = MAX (start, stop); - RFIP->plusstrand = (start < stop); - RFIP->numivals = 1; - RFIP->featdeftype = APPEARANCEITEM_Alignment; - RFIP->entityID = SAlnP->idx.entityID; - RFIP->itemID = SAlnP->idx.itemID; - RFIP->itemType = SAlnP->idx.itemtype; - labelbuf[0] = 0; - if (SeqAlignContentLabel(SAlnP, alignRow, labelbuf, sizeof(labelbuf) - 1, AIP->format)) - { - RFIP->ContentLabel = StringSave(labelbuf); + if (asip->stop < asip->start) { + swap = asip->stop; + asip->stop = asip->start; + asip->start = swap; } - if (stdSeg) - return RFIP; - - nsegs = AlnMgr2GetNumSegs(SAlnP); - if (nsegs <= 1) - return RFIP; + asip->currentStdSeg = NULL; + asip->currentSeg = 0; + + return asip->nsegs; +} + +/* + Given an AlignSegIterator return the information about the current segment + in the pointer arguments, and advance the iterator to the next segment. + Return false if there are no more segments in which case the output arguments + will not be changed. +*/ +static Boolean AlignSegIteratorNext( + AlignSegIteratorPtr asip, + Int4Ptr startOut, + Int4Ptr stopOut, + Uint1Ptr strandOut, + Uint1Ptr segTypeOut +) +{ + Int4 start, stop, swap; + Uint1 strand, segType; + Boolean stdSeg; + Int4 iseg; + + + if (asip == NULL) + return FALSE; /* bad argument */ + + /* iterate */ + asip->currentSeg++; + if (asip->currentSeg > asip->nsegs) /* no more segments */ + return FALSE; - RFIP->ivals = MemNew (2 * nsegs * sizeof (Int4)); - if (RFIP->ivals != NULL) - { - RFIP->numivals = 0; - i = 0; - for (iseg = 1; iseg <= nsegs; ++iseg) - { - /* get segment location in alignment coordinates */ - AlnMgr2GetNthSegmentRange(SAlnP, iseg, &alignStart, &alignStop); - /* convert to bioseq coordinates */ - start = AlnMgr2MapSeqAlignToBioseq(SAlnP, alignStart, alignRow); - if (alignStart != alignStop) - stop = AlnMgr2MapSeqAlignToBioseq(SAlnP, alignStop , alignRow); - else - stop = start; - - /* ignore gaps on the bioseq, zero length segments & errors */ - /* hence we may have less than nsegs ivals */ - if (start < 0 || stop < 0 || stop == start) - continue; - - /* Is this a gap on the BioSeq ? */ - row2 = 3 - alignRow; /* alignRow == 1 then row2 == 2; & vice versa. dim must be 2! */ - seq2Start = AlnMgr2MapSeqAlignToBioseq(SAlnP, alignStart, row2); - - if (seq2Start == -2 ) - continue; /* a gap */ + if (asip->strand == Seq_strand_minus) + iseg = asip->nsegs - asip->currentSeg + 1; + else + iseg = asip->currentSeg; + + stdSeg = (asip->sap->segtype == SAS_STD); + if ( ! stdSeg) { + Int4 alignStart, alignStop; + Int4 row2, seq2Start; + + strand = asip->strand; /* all segments have the same strand */ + /* get segment location in alignment coordinates */ + AlnMgr2GetNthSegmentRange(asip->sap, iseg, &alignStart, &alignStop); + /* convert to bioseq coordinates */ + start = AlnMgr2MapSeqAlignToBioseq(asip->sap, alignStart, asip->alignRow); + if (alignStart != alignStop) + stop = AlnMgr2MapSeqAlignToBioseq(asip->sap, alignStop , asip->alignRow); + else + stop = start; - RFIP->ivals[i++] = MIN(start, stop); - RFIP->ivals[i++] = MAX(start, stop); - RFIP->numivals++; - } + /* Is this a insert (a gap on the bioseq)? */ + if (start == -2) { + segType = AM_INSERT; + } else { + /* check the other sequence to see if there is a gap there. */ + if (asip->alignRow == 1) + row2 = 2; + else + row2 = 1; + seq2Start = AlnMgr2MapSeqAlignToBioseq(asip->sap, alignStart, row2); + + if (seq2Start == -2 ) + segType = AM_GAP; + else + segType = AM_SEQ; + } + } + else { /* stdSeg */ + asip->currentStdSeg = AlnMgr2GetNthStdSeg(asip->sap, iseg); + if (asip->currentStdSeg == NULL) + return FALSE; /* Logic Error. should not happen. */ + + AlnMgr2GetSeqRangeForSipInStdSeg(asip->currentStdSeg, asip->sip, &start, &stop, &strand, &segType); } - return RFIP; + if (stop < start) { + swap = start; + start = stop; + stop = swap; + } + + /* take care of output arguments */ + if (startOut) *startOut = start; + if (stopOut) *stopOut = stop; + if (strandOut) *strandOut = strand; + if (segTypeOut) *segTypeOut = segType; + + return TRUE; } + static RelevantFeatureItemPtr GetNextRFIPinFeatureFilter ( FilterProcessStatePtr FPSP ) @@ -2856,8 +3472,8 @@ static RelevantFeatureItemPtr GetNextRFIPinFeatureFilter ( if (FPSP->featuresProcessed [featSP->featureBlockOffset + featSP->indexInBlock] || (! currentFIP->IncludeFeature [RFIP->featdeftype])) continue; if (currentFIP->MatchStrand != BothStrands) { - if (currentFIP->MatchStrand == MinusStrand && RFIP->plusstrand) continue; - if (currentFIP->MatchStrand == PlusStrand && !RFIP->plusstrand) continue; + if (currentFIP->MatchStrand == MinusStrand && RFIP->featstrand != Seq_strand_minus) continue; + if (currentFIP->MatchStrand == PlusStrand && RFIP->featstrand != Seq_strand_plus) continue; } FPSP->featuresProcessed [featSP->featureBlockOffset + featSP->indexInBlock] = TRUE; break; @@ -2874,7 +3490,7 @@ static RelevantFeatureItemPtr GetNextRFIPinFilterItem ( { AlignmentFilterStatePtr alignSP; - RelevantFeatureItemPtr RFIP; + RelevantFeatureItemPtr RFIP = NULL; ViewerContextPtr vContext; FilterItemPtr currentFIP; @@ -2890,10 +3506,11 @@ static RelevantFeatureItemPtr GetNextRFIPinFilterItem ( return NULL; case AlignmentFilter: alignSP = &FPSP->state.align; - do { + while (!AlignmentFilterStateDone(alignSP)) { RFIP = GetNextRFIPinAlignmentFilter (FPSP); - if (RFIP != NULL) return RFIP; - } while (alignSP->SAPcurrent != NULL); + if (RFIP != NULL) + return RFIP; + } /* note: if control reaches here, then RFIP == NULL */ break; case FeatureFilter: @@ -2924,7 +3541,7 @@ static Boolean AddFeatureToRow ( if (row == NULL || RFIP == NULL) return FALSE; if (!SkipSmearTest && row->rowFeatureCount && - TestForSmear (RFIP, (RelevantFeatureItemPtr) row->feats->data.ptrvalue, vContext)) { + TestForSmear (RFIP, (RelevantFeatureItemPtr) row->feats->data.ptrvalue, vContext->viewScale)) { /* if the last feature was not a smear-in-progress, allocate newRFIP, else re-use the current one */ oldRFIP = (RelevantFeatureItemPtr) row->feats->data.ptrvalue; if (oldRFIP->entityID == 0 && oldRFIP->itemID == 0) { @@ -3033,7 +3650,7 @@ static Boolean mRNAmatchesCDS ( /* the mRNA must be the larger feature */ if (CDS->Left < mRNA->Left || CDS->Right > mRNA->Right) return FALSE; /* check strands */ - if (CDS->plusstrand != mRNA->plusstrand) return FALSE; + if (CDS->featstrand != mRNA->featstrand) return FALSE; /* trivial case */ if (CDS->numivals == 1 && mRNA->numivals == 1) return TRUE; /* . . . and the intervals must line up */ @@ -3082,6 +3699,9 @@ static Uint2 GeneProductsLayoutInternal ( Int4 newLeft, featureStart, rowMaxRight; RenderInput dummyRI; RFIPgroupPtr currentGroup; + Uint4 viewScale; + + viewScale = FPSP->vContext->viewScale; if (firstRow == NULL) return 0; @@ -3250,7 +3870,8 @@ static Uint2 GeneProductsLayoutInternal ( break; } rowMaxRight = thisRow2->layoutData.intvalue; - if (tRFIPentry->decorationLeft < rowMaxRight) { + if ( tRFIPentry->decorationLeft <= rowMaxRight || + NoVisibleGap(tRFIPentry->decorationLeft, rowMaxRight, viewScale) ) { foundRows = FALSE; if (thisRow2->next == NULL) { rows++; @@ -3331,6 +3952,9 @@ static Uint2 BubbleUpLayout ( RelevantFeatureItemPtr RFIP; InternalRowPtr thisRow, lastRow; RenderInput dummyRI; + Uint4 viewScale; + + viewScale = FPSP->vContext->viewScale; /* This uses InternalRow.layoutData as an Int4, which stores the (x) offset of the last used pixel. so a feature starting at (internalRow.layoutData + 1) or greater can be placed in the same row @@ -3354,7 +3978,8 @@ static Uint2 BubbleUpLayout ( featureStart = dummyRI.decorationLeft; for (thisRow = firstRow; thisRow != NULL; thisRow = thisRow->next) { rowMaxRight = thisRow->layoutData.intvalue; - if (featureStart >= rowMaxRight) { + if (featureStart >= rowMaxRight && + ! NoVisibleGap(featureStart, rowMaxRight, viewScale) ) { AddFeatureToRow (thisRow, RFIP, FALSE, FPSP); rowMaxRight = MAX (rowMaxRight, dummyRI.decorationRight); thisRow->layoutData.intvalue = rowMaxRight; @@ -3384,23 +4009,27 @@ static Uint2 SingleRowLayout ( Uint4 smearStart, smearStop; Uint1 smearFeatdeftype; ViewerContextPtr vContext; + Uint4 viewScale; Boolean adjacentNoGap; Boolean tooNarrow; Boolean smearing = FALSE, justSmeared = FALSE; vContext = FPSP->vContext; - + viewScale = vContext->viewScale; lastRFIP = GetNextRFIPinFilterItem (FPSP); if (lastRFIP == NULL) return 0; smearFeatdeftype = lastRFIP->featdeftype; while ((RFIP = GetNextRFIPinFilterItem (FPSP)) != NULL) { - adjacentNoGap = TestForSmearOverlap (lastRFIP->Right + 2 * vContext->viewScale, RFIP->Left, vContext); - tooNarrow = TestForSmearOverlap (RFIP->Left + 4 * vContext->viewScale, RFIP->Right, vContext); + adjacentNoGap = PixelsBetweenSeqCoords(lastRFIP->Right, RFIP->Left, viewScale) < 2; /* was 3 */ + /* TestForSmearOverlap (lastRFIP->Right + 2 * vContext->viewScale, RFIP->Left, vContext); */ + tooNarrow = PixelsBetweenSeqCoords(RFIP->Left, RFIP->Right, viewScale) < 5; + /* TestForSmearOverlap (RFIP->Left + 4 * vContext->viewScale, RFIP->Right, vContext); */ if (adjacentNoGap && tooNarrow) { if (smearing == FALSE) { - tooNarrow = TestForSmearOverlap (lastRFIP->Left + 4 * vContext->viewScale, lastRFIP->Right, vContext); + tooNarrow = PixelsBetweenSeqCoords(lastRFIP->Left, lastRFIP->Right, viewScale) < 5; + /* TestForSmearOverlap (lastRFIP->Left + 4 * vContext->viewScale, lastRFIP->Right, vContext); */ if (tooNarrow) { smearStart = lastRFIP->Left; } else { @@ -3426,8 +4055,10 @@ static Uint2 SingleRowLayout ( if (lastRFIP == NULL) return 1; lastRFIP->Left = smearStart; lastRFIP->Right = smearStop; - lastRFIP->plusstrand = TRUE; + lastRFIP->featstrand = Seq_strand_unknown; + lastRFIP->circularSpanningOrigin = FALSE; lastRFIP->LeftEnd = lastRFIP->RightEnd = EndAbsolute; + lastRFIP->circularSpanningOrigin = FALSE; lastRFIP->featdeftype = smearFeatdeftype; lastRFIP->numivals = 1; ValNodeAddPointer (&FPSP->needFreeList, 0, lastRFIP); @@ -3444,7 +4075,9 @@ static Uint2 SingleRowLayout ( if (RFIP == NULL) return 1; RFIP->Left = smearStart; RFIP->Right = smearStop; - RFIP->plusstrand = TRUE; + RFIP->featstrand = Seq_strand_unknown; + RFIP->circularSpanningOrigin = FALSE; + RFIP->LeftEnd = RFIP->RightEnd = EndAbsolute; RFIP->featdeftype = smearFeatdeftype; RFIP->numivals = 1; @@ -3944,7 +4577,8 @@ static Boolean LIBCALLBACK Asn2gphSegmentExploreProc ( } RFIP->numivals = 1; RFIP->featdeftype = 0; - RFIP->plusstrand = (context->strand == Seq_strand_plus); + RFIP->featstrand = context->strand; + RFIP->circularSpanningOrigin = FALSE; return TRUE; } @@ -4396,7 +5030,7 @@ static void CleanGSP (BigScalar calldata) static GphSentPtr AddGphSentinelToPicture (SeqGraphPtr sgp, BioseqPtr bsp, SegmenT pict, Int4 scaleX, Int4 top, Int2 start, - Uint1Ptr uRGB) + Uint1Ptr uRGB, Boolean drawScale) { Int4 axis; GphSentPtr gsp; @@ -4482,13 +5116,15 @@ static GphSentPtr AddGphSentinelToPicture (SeqGraphPtr sgp, BioseqPtr bsp, } gsp->seg = seg = CreateSegment (pict, 0, 0); gsp->bottom = top - (max - min) - 20; - AddSegRect (seg, FALSE, 0); - if (sgp->title != NULL) /* StringHasNoText -- vibforms */ + if (drawScale && sgp->title != NULL) /* StringHasNoText -- vibforms */ { if (StringLen (sgp->title) > 0) { - AddLabel (seg, (gsp->box.left + gsp->box.right) / 2, top, + AddLabel (seg, + /* (gsp->box.left + gsp->box.right) / 2, */ + (start + bsp->length) / 2, + top, sgp->title, SMALL_TEXT, 0, MIDDLE_CENTER, 0); } } @@ -4501,28 +5137,31 @@ static GphSentPtr AddGphSentinelToPicture (SeqGraphPtr sgp, BioseqPtr bsp, gsp->axis = axis; gsp->bottom += 10; - if (is_phrap) - { - for (i = 0; i <=100; i += 20) { - sprintf (str, "%ld", (long) i); - AddLabel (seg, gsp->box.left, gsp->bottom + i, str, - SMALL_TEXT, 5, MIDDLE_LEFT, 0); - } - } - else + if (drawScale) { - sprintf (str, "%ld", (long) max); - AddLabel (seg, gsp->box.left, top-10, str, - SMALL_TEXT, 5, MIDDLE_LEFT, 0); - sprintf (str, "%ld", (long) min); - AddLabel (seg, gsp->box.left, gsp->bottom-10, str, - SMALL_TEXT, 5, MIDDLE_LEFT, 0); - if (min < 0 && max > 0) - { - sprintf (str, "%ld", 0L); - AddLabel (seg, gsp->box.left, gsp->bottom-min-10, str, - SMALL_TEXT, 5, MIDDLE_LEFT, 0); - } + if (is_phrap) + { + for (i = 0; i <=100; i += 20) { + sprintf (str, "%ld", (long) i); + AddLabel (seg, gsp->box.left, gsp->bottom + i, str, + SMALL_TEXT, 5, MIDDLE_LEFT, 0); + } + } + else + { + sprintf (str, "%ld", (long) max); + AddLabel (seg, gsp->box.left, top-10, str, + SMALL_TEXT, 5, MIDDLE_LEFT, 0); + sprintf (str, "%ld", (long) min); + AddLabel (seg, gsp->box.left, gsp->bottom-10, str, + SMALL_TEXT, 5, MIDDLE_LEFT, 0); + if (min < 0 && max > 0) + { + sprintf (str, "%ld", 0L); + AddLabel (seg, gsp->box.left, gsp->bottom-min-10, str, + SMALL_TEXT, 5, MIDDLE_LEFT, 0); + } + } } gsp->snt = AddSntRectangle (seg, gsp->box.left, gsp->box.top, @@ -4536,17 +5175,26 @@ static void VisitAndListGraphs (SeqGraphPtr sgp, Pointer userdata) { GphSentPtr gsp; ViewerContextPtr vContext; - + Boolean drawScale = FALSE; + vContext = (ViewerContextPtr) userdata; if (vContext == NULL) return; if (vContext->gphseg == NULL) { vContext->gphseg = CreateSegment (vContext->drawOnMe, 0, 0); + + /* + this first time 'drawScale' stuff here and in AddGphSentinelToPicture + assumes that all the graphs on this bioseq are the same type + use the same legend and have the same label. + */ + AddSegRect (vContext->gphseg, FALSE, 0); /* draw box around all the graphs, not each one individually */ + drawScale = TRUE; /* only draw scale on the first graph */ } gsp = AddGphSentinelToPicture (sgp, vContext->BSP, vContext->gphseg, vContext->viewScale, vContext->gphyOffset, - 0, NULL); + 0, NULL, drawScale); if (gsp == NULL) return; vContext->gphheight = MAX (vContext->gphheight, gsp->box.top - gsp->box.bottom); } @@ -4584,6 +5232,671 @@ static void ResetFilterState ( } } + +/* + Order by accession (label), strand and location + for sorting. +*/ +static int LIBCALLBACK CompareAlignNameLoc(VoidPtr ptr1, VoidPtr ptr2) +{ + SeqAlignSortInfoPtr saip1, saip2; + Int2 labelcomp; + + if (ptr1 != NULL && ptr2 != NULL) { + saip1 = (SeqAlignSortInfoPtr) ptr1; + saip2 = (SeqAlignSortInfoPtr) ptr2; + + labelcomp = StrNCmp(saip1->label, saip2->label, MAX_ALIGN_SORT_LABEL); + if (labelcomp != 0) + return labelcomp; + + if (saip1->strand < saip2->strand) + return -1; + if (saip1->strand > saip2->strand) + return 1; + + if (saip1->start < saip2->start) + return -1; + if (saip1->start > saip2->start) + return 1; + if (saip1->stop < saip2->stop) + return -1; + if (saip1->stop > saip2->stop) + return 1; + } + return 0; +} + +static int LIBCALLBACK ScoreCompare( VoidPtr p1, VoidPtr p2) +{ + if (p1 != NULL && p2 != NULL) { + Int4 i1 = * (Int4Ptr) p1; + Int4 i2 = * (Int4Ptr) p2; + + return i1 - i2; + } + return 0; +} + +/* + Take a number (rawscore) between min and max (inclusive) + and linearly scale it into a number from 1 to ACCUMVALUE_MAX/256. + We divide by 256 since we will be adding these numbers together when smearing. + Hopefully we won't have more than 256 with large scores at any one point :) + Do not call if min >= max. +*/ +AccumValue_t NormaliseScore(Int4 rawscore, Int4 min, Int4 max) +{ + AccumValue_t retval; + FloatHi fscore = rawscore - min; + fscore *= ACCUMVALUE_MAX / 256 - 1; + fscore /= (max - min); + retval = fscore + 1; + return retval; +} + + +static void FindCutoffScore(SeqAlignPtr sap, Int4 alignCnt, AlignmentFilterStatePtr afsp) +{ + SeqAlignPtr sapIter; + Int4Ptr allScores; + Int4 i; + /* Int4 cutoffScore; /* not normalized */ + + /* make array to hold all the scores. */ + allScores = MemNew(alignCnt * sizeof(Int4)); + if (allScores == NULL) + return; + + /* get all the scores */ + i = 0; + for (sapIter = sap; sapIter != NULL; sapIter = sapIter->next) { + allScores[i++] = WeightFromAlignScore(sapIter, afsp->scoreType); + } + + /* sort them */ + HeapSort ( allScores, alignCnt, sizeof(Int4), ScoreCompare); + + /* find, normalise and return the cutoffPercent score + and the min & max scores so we can normalise the rest of the scores later. + */ + afsp->minScore = allScores[0]; + afsp->maxScore = allScores[alignCnt - 1]; + afsp->cutoffScoreHi = ACCUMVALUE_MAX; /* could add other controls to set this. */ +/* Cutoff by actual score, not by percentage. + if (afsp->cutoffPercent == 100 || + afsp->scoreType == NLM_SCORE_COUNT || + afsp->minScore >= afsp->maxScore ) { + afsp->cutoffScore = 0; + } + else { + cutoffScore = allScores[ (100 - afsp->cutoffPercent) * alignCnt/100 ]; + afsp->cutoffScore = NormaliseScore(cutoffScore, afsp->minScore, afsp->maxScore); + } +*/ + MemFree(allScores); +} + + +/* Gather all the SeqAligns whose normalised score is less than the cutoff score */ +static void GatherAlignInfo( + SeqAlignPtr sap, + Int4 alignCnt, + SeqIdPtr bioSeqId, + AlignmentFilterStatePtr afsp +) +{ + SeqAlignSortInfoPtr infoArray = NULL; + Int4 infoIndex; + SeqAlignPtr sapIter; + Int4 nrows, alignRow; + Int4 start, stop, swap; + Uint1 strand; + Int4 rawScore; + AccumValue_t normScore; + + infoArray = MemNew(alignCnt * sizeof(SeqAlignSortInfo)); + if (infoArray == NULL) + return; + + infoIndex = 0; + for (sapIter = sap; sapIter != NULL; sapIter = sapIter->next) + { + /* is this alignment in the top percentile? */ + if (afsp->scoreType != NLM_SCORE_COUNT && afsp->minScore < afsp->maxScore ) { + rawScore = WeightFromAlignScore(sapIter, afsp->scoreType); + normScore = NormaliseScore( rawScore, afsp->minScore, afsp->maxScore); + /* if (normScore < afsp->cutoffScore || afsp->cutoffScoreHi < normScore) */ + if (rawScore < afsp->cutoffScore || afsp->cutoffScoreHi < rawScore) + { + continue; + } + } else { + normScore = 1; + } + + if (!AlnMgr2IndexSingleChildSeqAlign (sapIter)) continue; /* make sure we are indexed */ + + /* get dimensions of this alignment (number of sequences aligned) */ + nrows = AlnMgr2GetNumRows(sapIter); + if (nrows < 1) { + nrows = sapIter->dim; + } + if (nrows != 2) { /* can't handle 3+ dimension alignments */ + continue; + } + + /* Get the beginning and end points of this alignment in Bioseq coords. */ + if (sapIter->segtype != SAS_STD) { + /* not Std Seg alignment, use indexed functions */ + alignRow = AlnMgr2GetFirstNForSipList (sapIter, bioSeqId); + if (alignRow == -1) { + continue; + } + AlnMgr2GetNthSeqRangeInSA(sapIter, alignRow, &start, &stop); + strand = AlnMgr2GetNthStrand(sapIter, alignRow); + } else { + /* Std Seg alignment. Use special function */ + AlnMgr2GetSeqRangeForSipInSAStdSeg(sapIter, bioSeqId, &start, &stop, &strand); + } + if (start < 0) { + continue; + } + if (stop < start) { + swap = stop; + stop = start; + start = swap; + } + + /* populate the structure we will use to sort on. */ + infoArray[infoIndex].start = start; + infoArray[infoIndex].stop = stop; + infoArray[infoIndex].strand = strand; + infoArray[infoIndex].sap = sapIter; + infoArray[infoIndex].normScore = normScore; + if (!SeqAlignContentLabel(sapIter, bioSeqId, infoArray[infoIndex].label, MAX_ALIGN_SORT_LABEL, PRINTID_TEXTID_ACC_VER)) { + infoArray[infoIndex].label[0] = 0; + } + ++infoIndex; + } + + afsp->alignSortedLen = infoIndex; + + if (infoIndex == 0) { + MemFree(infoArray); + infoArray = NULL; + } + afsp->alignSorted = infoArray; +} + +static Boolean AlignmentFilterStateInit( + SeqAlignPtr sap, /* the head of hte chain of sequence alignments from the bioseq */ + SeqIdPtr sid, /* the id of the bioseq so we know how we are viewing the alignments */ + AlignmentFilterStatePtr afsp, /* What we are initializing. */ + GraphicViewExtrasPtr extras /* contains the score cuttoff percentage and the kind of scores we use */ +) +{ + SeqAlignPtr sapIter; + Int4 alignCnt; + Uint1 scoreType = NLM_SCORE_COUNT; + Int2 i = 0; + + if (sap == NULL || sid == NULL || afsp == NULL) + return FALSE; + + /* what kind of score will we use to weight the alignments? */ + if (extras && extras->alignScoreName) { + scoreType = StringIndexInStringList (extras->alignScoreName, AlnScoreStrings); + if (scoreType >= NLM_SCORE_TOOBIG) + scoreType = NLM_SCORE_COUNT; + } + afsp->scoreType = scoreType; + + /* what percentile does an alignments score have to be to be displayed? */ + if (extras && extras->alignScoreCutoff) { + i = StringIndexInStringList (extras->alignScoreCutoff, AlnScoreCutoffStrings); + if (i < 0 || DIM (AlnScoreCutoffValues) <= i ) + i = 0; + } + /* afsp->cutoffPercent = AlnScoreCutoffValues[i]; */ + if (AlnScoreCutoffValues[i] < 0) { + afsp->scoreType = NLM_SCORE_COUNT; + } else { + afsp->scoreType = NLM_SCORE_BIT; + afsp->cutoffScore = AlnScoreCutoffValues[i]; + } + + /* how many alignments? Count one time now */ + alignCnt = 0; + for (sapIter = sap; sapIter != NULL; sapIter = sapIter->next) { + ++alignCnt; + } + + FindCutoffScore(sap, alignCnt, afsp); + + GatherAlignInfo(sap, alignCnt, sid, afsp); + if (afsp->alignSorted == NULL || afsp->alignSortedLen == 0) { + /* couldn't allocate memory, or no alignments - nothing to do. */ + return FALSE; + } + /* sort the alignments, first by accession, then by location on the bioseq. */ + HeapSort(afsp->alignSorted, afsp->alignSortedLen, sizeof(SeqAlignSortInfo), CompareAlignNameLoc); + afsp->alignIndex = 0; + + return TRUE; +} + +static Boolean AlignmentFilterStateDone(AlignmentFilterStatePtr afsp) +{ + if (afsp->alignSorted != NULL && + afsp->alignIndex < afsp->alignSortedLen) + return FALSE; + return TRUE; +} + + +static void AlignmentFilterStateFree( AlignmentFilterStatePtr afsp) +{ + if (afsp->alignSorted != NULL) + MemFree(afsp->alignSorted); + afsp->alignSorted = NULL; + afsp->alignSortedLen = 0; +} + + + +static Int4 WeightFromAlignScore(SeqAlignPtr sap, Uint1 scoreType) +{ + Int4 weight = 1; + Int4 score, number; + Nlm_FloatHi bit_score, evalue; + + if (GetScoreAndEvalue(sap, &score, &bit_score, &evalue, &number)) { + /* evaluate scores and get weight */ + switch (scoreType) { + case NLM_SCORE_SCORE : + weight = score; + break; + case NLM_SCORE_BIT : + weight = bit_score; + break; + case NLM_SCORE_EVALUE : + if (evalue > 0) { + weight = -log(evalue); + } + else { /* 0 is the best value. */ + /* + We can't use the maxScore here since we do not know it yet + since this is where we collect the values. + Our sample data has -log(evalue) ranging from 25 - 429 + so 500 just has to be bigger than anything else we will encounter. + It will get normalised latter with it as the maxScore. + + We could put a special sentinel value (very large or negative) here + that gets replaced with the real maxScore later. + (But then make sure it gets skipped when calculating the max and min). + */ + weight = 500; + } + break; + case NLM_SCORE_NUMBER : + weight = number; + break; + case NLM_SCORE_COUNT : + default: + weight = 1; + } + } + + return weight; +} + +/* uncomment to use 'chunked' arrays (all allocations in 64K chunks) for making the Alignment Smear */ +/* #define CHUNKED_ACCUMULATOR 1 /* */ + +#ifdef CHUNKED_ACCUMULATOR +/* + ChunkedArray + An array allocated, not continguously in memory, but in chunks to reduce + the memory allocation strain. + Use AccumValue_t as the data type of the array elements. + memory accesses are unchecked. +*/ +/* should be a power of 8 so as to be evenly divisble by sizeof(AccumValue_t) */ +#define CA_CHUNK_SIZE (64*1024) +#define CA_ITEMSPERCHUNK (CA_CHUNK_SIZE/sizeof(AccumValue_t)) + +typedef struct ChunkedArray_struct { + AccumValuePtr_t PNTR chunks; /* for data access */ + ValNodePtr chunkList; /* for memory management */ + size_t nchunks; +} PNTR ChunkedArray; + + +static void FreeChunkedArray(ChunkedArray* ca); + +static ChunkedArray +NewChunkedArray(size_t size) +{ + ChunkedArray newca; + AccumValuePtr_t aChunk; + size_t itemsPerChunk = CA_ITEMSPERCHUNK; + size_t nchunks = 1 + size / itemsPerChunk; + Int4 i; + + newca = MemNew(sizeof(struct ChunkedArray_struct)); + if (newca == NULL) + return NULL; + + newca->nchunks = nchunks; + newca->chunks = MemNew(sizeof(AccumValuePtr_t) * nchunks); + if ( newca->chunks == NULL) { + FreeChunkedArray(&newca); + return NULL; + } + + for (i = 0; i < nchunks; ++i) { + aChunk = MemNew(CA_CHUNK_SIZE); + if (aChunk == NULL || ValNodeAddPointer (&newca->chunkList, 0, aChunk) == NULL) { + FreeChunkedArray(&newca); + return NULL; + } + newca->chunks[i] = aChunk; + } + + return newca; +} + +static void +FreeChunkedArray(ChunkedArray* ca) +{ + + if (ca == NULL || *ca == NULL) + return; + + ValNodeFreeData((*ca)->chunkList); + MemFree((*ca)->chunks); + MemFree(*ca); + *ca = NULL; +} + +static void +SetCA(ChunkedArray ca, size_t index, AccumValue_t value) +{ + size_t chunk_index = index / CA_ITEMSPERCHUNK; + size_t val_index = index % CA_ITEMSPERCHUNK; + + if (chunk_index > ca->nchunks) + return; + ca->chunks[chunk_index][val_index] = value; +} + +static AccumValue_t +GetCA(ChunkedArray ca, size_t index) +{ + size_t chunk_index = index / CA_ITEMSPERCHUNK; + size_t val_index = index % CA_ITEMSPERCHUNK; + + if (chunk_index > ca->nchunks) + return 0; + return ca->chunks[chunk_index][val_index]; +} + +#endif /* CHUNKED_ACCUMULATOR */ + +/* + Interval Accumulator + An object which can add or in some way (specified by accumop) intervals on a sequence, + then from which can be extracted the resulting intervals. +*/ +typedef enum AccumlatorOp { + NLM_SUM_WEIGHT = 0, + NLM_MAX_WEIGHT +} AccumulatorOp; + +typedef struct IntervalAccumulator { +#ifdef CHUNKED_ACCUMULATOR + ChunkedArray densities; + ChunkedArray gapDensities; +#else + AccumValuePtr_t densities; + BoolPtr gapDensities; +#endif + Uint4 densitiesLength; + AccumulatorOp accumOp; + Uint2 minDensity; +} IntervalAccumulator, PNTR IntervalAccumulatorPtr; + +static IntervalAccumulatorPtr +NewIntervalAccumulator(Uint4 length, AccumulatorOp accumOp, AccumValue_t minDensity) +{ + IntervalAccumulatorPtr iap = NULL; + + iap = MemNew(sizeof(IntervalAccumulator)); + if (NULL == iap) + return NULL; + + iap->accumOp = accumOp; + iap->densitiesLength = length; + if (minDensity == 0) + minDensity = 1; + iap->minDensity = minDensity; /* the smallest density we will report as an interval */ +#ifdef CHUNKED_ACCUMULATOR + iap->densities = NewChunkedArray(length); +#else + iap->densities = MemNew(length * sizeof(AccumValue_t)); +#endif + if (NULL == iap->densities) { + MemFree(iap); + return NULL; + } +#ifdef CHUNKED_ACCUMULATOR + iap->gapDensities = NewChunkedArray(length); + if (NULL == iap->gapDensities) { + FreeChunkedArray(&iap->densities); + MemFree(iap); + iap = NULL; + } +#else + iap->gapDensities = MemNew(length * sizeof(Boolean)); + if (NULL == iap->gapDensities) { + MemFree(iap->densities); + MemFree(iap); + iap = NULL; + } +#endif + return iap; +} + +static void +FreeIntervalAccumulator(IntervalAccumulatorPtr PNTR iapp) +{ + IntervalAccumulatorPtr iap; + + if (iapp == NULL || *iapp == NULL) return; + iap = *iapp; +#ifdef CHUNKED_ACCUMULATOR + FreeChunkedArray(&iap->gapDensities); + FreeChunkedArray(&iap->densities); +#else + MemFree(iap->gapDensities); + MemFree(iap->densities); +#endif + MemFree(iap); + *iapp = NULL; +} + +static void +AccumulateInterval(IntervalAccumulatorPtr iap, Uint4 start, Uint4 stop, AccumValue_t weight, Boolean isGap) +{ + Int4 i; +#ifdef CHUNKED_ACCUMULATOR + AccumValue_t av; +#endif + + if (NULL == iap) return; + if (iap->densitiesLength <= start) return; + if (weight <= 0) return; + + stop = MIN(stop, iap->densitiesLength - 1); + + if (!isGap) { + switch (iap->accumOp) { + case NLM_MAX_WEIGHT : + for (i = start; i <= stop; i++) { +#ifdef CHUNKED_ACCUMULATOR + if (weight > GetCA(iap->densities, i)) + SetCA(iap->densities, i, weight); +#else + if (weight > iap->densities[i]) + iap->densities[i] = weight; +#endif + } + break; + case NLM_SUM_WEIGHT : + default : + for (i = start; i <= stop; i++) { +#ifdef CHUNKED_ACCUMULATOR + av = GetCA(iap->densities, i) + weight; + if (av < ACCUMVALUE_MAX) + SetCA(iap->densities, i, av); +#else + if (iap->densities[i] + weight < ACCUMVALUE_MAX) + iap->densities[i] += weight; +#endif + } + break; + } + } + else { + /* ignore weight in gaps */ + for (i = start; i <= stop; i++) { +#ifdef CHUNKED_ACCUMULATOR + SetCA(iap->gapDensities, i, TRUE); +#else + iap->gapDensities[i] = TRUE; +#endif + } + } +} + +static Uint2 GetMaxDensity(IntervalAccumulatorPtr iap) +{ + AccumValue_t maxDensity = 0, av; + Int4 i; + + if (NULL == iap) return 0; + for (i = 0; i < iap->densitiesLength; i++) { +#ifdef CHUNKED_ACCUMULATOR + av = GetCA(iap->densities, i); +#else + av = iap->densities[i]; +#endif + if (av > maxDensity) + maxDensity = av; + } + return maxDensity; +} + +static Uint4 +GetIntervalFromAccumulator( + IntervalAccumulatorPtr iap, + Uint4 n, + Uint4Ptr startp, + Uint4Ptr stopp, + AccumValuePtr_t densityp, + BoolPtr isGapp +) +{ + Uint4 start, stop; + AccumValue_t density = 0; + Boolean isGap = FALSE; + + if (NULL == iap) return FALSE; + + /* skip over empty spaces */ +/* Don't skip over them. Report them as an interval with gap = false and density = 0. + for ( ; n < iap->densitiesLength; n++) { +#ifdef CHUNKED_ACCUMULATOR + if (GetCA(iap->densities, n) >= iap->minDensity || + GetCA(iap->gapDensities, n)) +#else + if (iap->densities[n] >= iap->minDensity || + iap->gapDensities[n]) +#endif + break; + } +*/ + if (n >= iap->densitiesLength) + return 0; + + start = n; +#ifdef CHUNKED_ACCUMULATOR + if (GetCA(iap->densities, start) >= iap->minDensity) +#else + if (iap->densities[start] >= iap->minDensity) +#endif + { + /* an block */ +#ifdef CHUNKED_ACCUMULATOR + density = GetCA(iap->densities, start); +#else + density = iap->densities[start]; +#endif + isGap = FALSE; + /* scan for end of block */ + for ( ; n < iap->densitiesLength; n++) { +#ifdef CHUNKED_ACCUMULATOR + if (GetCA(iap->densities, start) != GetCA(iap->densities, n)) +#else + if (iap->densities[start] != iap->densities[n]) +#endif + break; + } + } +#ifdef CHUNKED_ACCUMULATOR + else if (GetCA(iap->gapDensities, start)) +#else + else if (iap->gapDensities[start]) +#endif + { /* assert gapDensities[n] == TRUE && densities[n] < minDensity */ + /* a gap */ + density = 0; + isGap = TRUE; + /* scan for end of the gap */ + for ( ; n < iap->densitiesLength; n++) { +#ifdef CHUNKED_ACCUMULATOR + if (! GetCA(iap->gapDensities, n) || GetCA(iap->densities, n) > 0) +#else + if (!iap->gapDensities[n] || iap->densities[n] > 0) +#endif + break; + } + } else { /* a space, not a gap or a block */ + density = 0; + isGap = FALSE; + /* scan for end of space */ + for ( ; n < iap->densitiesLength; n++) { +#ifdef CHUNKED_ACCUMULATOR + if (GetCA(iap->gapDensities, n) || GetCA(iap->densities, n) > 0) +#else + if (iap->gapDensities[n] || iap->densities[n] > 0) +#endif + break; + } + } + + stop = n; + + if (startp) *startp = start; + if (stopp) *stopp = stop; + if (densityp) *densityp = density; + if (isGapp) *isGapp = isGap; + + return n; +} + + static Uint2 SmearAlignments ( FilterProcessStatePtr FPSP, ViewerContextPtr vContext @@ -4597,166 +5910,255 @@ static Uint2 SmearAlignments ( FilterItemPtr FIP; AlignmentFilterStatePtr alignSP; - Int4 alignRow, start, stop, weight, swap, maxDensity, i, length; + SeqAlignSortInfoPtr alignSorted; + Int4 alignSortedLen; + Int4 alignIndex; + Int4 start, stop, maxDensity; Uint1 color[3], col; Uint1 minCol = 224; /* density == min -> light gray */ Uint1 maxCol = 0; /* density == max -> black */ - Uint2Ptr densities, gapDensities; + + IntervalAccumulatorPtr plusIAP = NULL, minusIAP = NULL; + Uint4 accumPos; + Uint4 begin, end; + Int4 space_pixs; + Boolean isGap; + AccumValue_t weight; + AccumValue_t density; + + Boolean smearedAlignsPlus = FALSE, smearedAlignsMinus = FALSE; + AccumulatorOp sumOrMax = NLM_SUM_WEIGHT; + Uint1 scoreType = NLM_SCORE_COUNT; + Boolean separateStrands; const Uint1 minDensity = 1; /* minimum density we will display. */ SegmenT seg; - Boolean empty = TRUE; + CharPtr annotName; + Int4 height = 0; + Uint2 space_line_height = 2; if (FPSP == NULL || vContext == NULL) return 0; alignSP = &FPSP->state.align; - - /* get the Appearance item for alignments */ + alignSorted = alignSP->alignSorted; + alignSortedLen = alignSP->alignSortedLen; + + /* get the Appearance item for alignments */ AIP = vContext->AppPtr->FeaturesAppearanceItem[APPEARANCEITEM_Alignment]; + /* get the bioseq's id for picking out the right part of the alignments */ BSP = vContext->BSP; SID = BSP->id; - densities = MemNew (sizeof (Uint2) * vContext->seqLength / vContext->viewScale); - if (densities == NULL) return 0; - gapDensities = MemNew (sizeof (Uint2) * vContext->seqLength / vContext->viewScale); - if (gapDensities == NULL) return 0; - - /* for all the alignments in this list (from a single annotation in this BioSeq) */ - for (SAP = alignSP->SAPhead; SAP != NULL; SAP = SAP->next) + + /* Get this annotation's name to decide how to display this. */ + annotName = GetSeqAnnotName(vContext->currentSAP); + separateStrands = FALSE; + if (StringStr(annotName, "BLASTX - swissprot")) + separateStrands = TRUE; + else if (StringStr(annotName, "BLASTN - mrna")) + separateStrands = TRUE; + else if (StringStr(annotName, "BLASTN - est")) + separateStrands = FALSE; + else if (StringStr(annotName, "BLASTN - nr")) + separateStrands = FALSE; + + plusIAP = NewIntervalAccumulator(vContext->seqLength, sumOrMax, minDensity); + if (plusIAP == NULL) goto smearAlignmentsDone; + minusIAP = NewIntervalAccumulator(vContext->seqLength, sumOrMax, minDensity); + if (minusIAP == NULL) goto smearAlignmentsDone; + + /* + for all the sorted alignments (from a single annotation in this BioSeq) + treat all alignments with the same accession as one alignment + */ + for (alignIndex = 0; + alignIndex < alignSortedLen; + ++alignIndex) { - Int4 nrows; - Int4 row2; + AlignSegIterator asi; Int4 nsegs; - Int4 iseg; - Int4 alignStart, alignStop; - Int4 seq2Start; - Boolean stdSeg = FALSE; - - if (!AlnMgr2IndexSingleChildSeqAlign (SAP)) continue; /* make sure we are indexed */ + Uint1 segType; + Uint1 strand; - nrows = AlnMgr2GetNumRows(SAP); - if (nrows < 1) - nrows = SAP->dim; - - if (nrows != 2) continue; /* can't handle 3+ dimension alignments */ + SAP = alignSorted[alignIndex].sap; - /* which row in the alignment is this BioSeq */ - alignRow = AlnMgr2GetFirstNForSip (SAP, SID); - if (alignRow == -1) + /* sanity checks */ + if (alignSorted[alignIndex].start < 0 || alignSorted[alignIndex].stop < 0) + continue; + + weight = alignSorted[alignIndex].normScore; + /* if (weight == 0) + continue; + */ + /* + at the begining of an alignment + if there was another alignment before this one, + with the same accession, strand and that alignment ended before this one begins, + treat that space as a gap. + */ + if (alignIndex > 0 && + StrNCmp(alignSorted[alignIndex - 1].label, alignSorted[alignIndex].label, MAX_ALIGN_SORT_LABEL) == 0 && + alignSorted[alignIndex - 1].strand == alignSorted[alignIndex].strand && + alignSorted[alignIndex - 1].stop < alignSorted[alignIndex].start) { - alignRow = AlignMgr2GetFirstNForStdSeg (SAP, SID); - if (alignRow == -1) continue; - stdSeg = TRUE; - } + start = alignSorted[alignIndex - 1].stop; + stop = alignSorted[alignIndex].start; - /* iterate through all the segments of this Alignment. */ - if (!stdSeg) { - nsegs = AlnMgr2GetNumSegs(SAP); - for (iseg = 1; iseg <= nsegs; ++iseg) - { - /* get segment location in alignment coordinates */ - AlnMgr2GetNthSegmentRange(SAP, iseg, &alignStart, &alignStop); - /* convert to bioseq coordinates */ - start = AlnMgr2MapSeqAlignToBioseq(SAP, alignStart, alignRow); - if (alignStart != alignStop) - stop = AlnMgr2MapSeqAlignToBioseq(SAP, alignStop , alignRow); - else - stop = start; - if (start < 0 || stop < 0) /* ignore gaps on the bioseq & errors */ - continue; - if (stop < start) { - swap = stop; - stop = start; - start = swap; - } - start /= vContext->viewScale; - stop /= vContext->viewScale; + if (strand != Seq_strand_minus || !separateStrands) + AccumulateInterval(plusIAP, start, stop, alignSorted[alignIndex].normScore, TRUE); + else + AccumulateInterval(minusIAP, start, stop, alignSorted[alignIndex].normScore, TRUE); + } - /* Is this a gap or an alignment segment? */ - row2 = 3 - alignRow; /* alignRow == 1 then row2 == 2; & vice versa. dim must be 2! */ - seq2Start = AlnMgr2MapSeqAlignToBioseq(SAP, alignStart, row2); - - weight = 1; /* make this based on alignment score !?? */ + /* + for each segment in an alignment + if the segment is block or a gap map it appropriately in the density arrays. + */ + nsegs = AlignSegIteratorCreate(SAP, SID, &asi); + if (nsegs == 0) + continue; + while (AlignSegIteratorNext(&asi, &start, &stop, &strand, &segType)) + { + if (segType == AM_INSERT || start < 0 || stop < 0) + continue; - if (seq2Start == -2 ) - { /* a gap */ - for (i = start; i <= stop; i++) - gapDensities[i] += weight; + if (segType == AM_GAP ) + { /* a gap */ + if (strand != Seq_strand_minus || !separateStrands) + AccumulateInterval(plusIAP, start, stop, weight, TRUE); + else + AccumulateInterval(minusIAP, start, stop, weight, TRUE); + } + else if (segType == AM_SEQ) + { /* a real alignment. */ + if (strand != Seq_strand_minus || !separateStrands) { + smearedAlignsPlus = TRUE; + AccumulateInterval(plusIAP, start, stop, weight, FALSE); } - else if (seq2Start >= 0) - { /* a real alignment. */ - weight = 1; /* do this correctly based on the alignment score !!!!! */ - for (i = start; i <= stop; i++) - densities[i] += weight; + else { + smearedAlignsMinus = TRUE; + AccumulateInterval(minusIAP, start, stop, weight, FALSE); } - - empty = FALSE; - } /* for iseg <= nsegs */ - } else { /* std segs */ - AlnMgr2GetNthSeqRangeInSAStdSeg (SAP, alignRow, &start, &stop); - - if (start < 0 || stop < 0) /* ignore gaps on the bioseq & errors */ - continue; - if (stop < start) { - swap = stop; - stop = start; - start = swap; } - start /= vContext->viewScale; - stop /= vContext->viewScale; - - weight = 1; /* make this based on alignment score !?? */ - - for (i = start; i <= stop; i++) - densities[i] += weight; - empty = FALSE; - } /* if std segs */ - } /* for SAP != NULL */ + } /* for all segments in an alignment */ + } /* for all alignments in an annotation */ - if (empty) - return 0; /* there was nothing to show. */ + if (!smearedAlignsPlus && !smearedAlignsMinus) + goto smearAlignmentsDone; /* there was nothing to show. */ DrawNamedAnnotBox(FPSP); FIP = (FilterItemPtr) FPSP->currentFilterVNP->data.ptrvalue; DrawFilterItemBoxLabel(FPSP, FIP); - - maxDensity = 0; - for (i = 0; i < vContext->seqLength / vContext->viewScale; i++) { - maxDensity = MAX (maxDensity, densities[i]); - } - seg = CreateSegment ( vContext->drawOnMe, 0, 0); - for (i = 0; i < vContext->seqLength / vContext->viewScale; i++) { + if (smearedAlignsPlus || !separateStrands) { + height += space_line_height; + maxDensity = GetMaxDensity(plusIAP); - for (length = 0; i + length < vContext->seqLength; length++) { - if (densities [i] != densities [i + length]) break; - } - /* convert density (1 - maxDensity) to "color" number (224 - 0) */ - if (densities [i] < minDensity) { - col = 255; - } else if (maxDensity == minDensity) { - col = 224; - } else { - col = (Uint1) (minCol + (densities[i] - minDensity)*(maxCol - minCol)/(maxDensity - minDensity)); - /* col = (Uint1) (224 - ((densities [i] * 192) / 256)); */ - } - color [2] = color [1] = color [0] = col; /* set to shade of grey. (minCol = 224) */ - if (col < 255) { - AddAttribute (seg, COLOR_ATT, color, 0, 0, 1, 0); - AddRectangle (seg, i * vContext->viewScale, FPSP->ceiling, (i + length) * vContext->viewScale, FPSP->ceiling - (AIP->Height), NO_ARROW, TRUE, 0); + accumPos = GetIntervalFromAccumulator(plusIAP, 0, &begin, &end, &density, &isGap); + while (accumPos > 0) { + + if (density > 0) { + /* convert (1 - maxDensity) to "color" number (224 - 0) */ + if (maxDensity == minDensity) { + col = minCol; + } else { + col = (Uint1) (minCol + (density - minDensity)*(maxCol - minCol)/(maxDensity - minDensity)); + } + color [2] = color [1] = color [0] = col; /* set to shade of grey. (minCol = 224) */ + AddAttribute (seg, COLOR_ATT, color, 0, 0, 1, 0); + AddRectangle (seg, begin, FPSP->ceiling - height, + end, FPSP->ceiling - height - (AIP->Height), NO_ARROW, TRUE, 0); + } + else if (isGap) { + AddAttribute (seg, COLOR_ATT, NULL, 0, 0, 1, 0); + AddLine (seg, begin, FPSP->ceiling - height - (AIP->Height)/2, + end, FPSP->ceiling - height - (AIP->Height)/2, NO_ARROW, 0); + } else { + /* put a small line above spaces between blocks we draw */ + if (0 < begin && end < vContext->seqLength) { /* ignore gaps at beginning and end of bioseq */ + ASSERT(!isGap && density == 0); + space_pixs = (end - begin)/vContext->viewScale; + /* if (3 <= space_pixs && space_pixs <= 10 && end < vContext->seqLength) { */ + if (space_pixs <= 20) { /* don't draw this line if it is more than 20 pixels long. */ + if (space_pixs < 3) { /* make sure bar is always at least 3 pixels long */ + int mid_point = end + begin; + end = (mid_point + 3 * vContext->viewScale) /2; + begin = (mid_point - 3 * vContext->viewScale) /2; + } + AddAttribute (seg, COLOR_ATT, NULL, 0, 0, 1, 0); + AddLine (seg, begin, FPSP->ceiling + space_line_height, + end - vContext->viewScale, FPSP->ceiling + space_line_height, NO_ARROW, 0); + } + } + } + accumPos = GetIntervalFromAccumulator(plusIAP, accumPos, &begin, &end, &density, &isGap); } - else if (gapDensities[i] > 0) { + /* put a little arrow to show this is the plus strand */ + if (separateStrands) { AddAttribute (seg, COLOR_ATT, NULL, 0, 0, 1, 0); - AddLine (seg, i * vContext->viewScale, FPSP->ceiling - (AIP->Height)/2, (i + length) * vContext->viewScale, FPSP->ceiling - (AIP->Height)/2, NO_ARROW, 0); + AddTextLabel (seg, 0 * vContext->viewScale, FPSP->ceiling - height - (AIP->Height)/2, + ">", FIP->GroupLabelFont, 1, MIDDLE_LEFT, 0); } - i += length - 1; + height += AIP->Height + FIP->IntraRowPaddingPixels; } - MemFree (densities); - MemFree (gapDensities); - - return AIP->Height; + if (smearedAlignsMinus) { + maxDensity = GetMaxDensity(minusIAP); + + accumPos = GetIntervalFromAccumulator(minusIAP, 0, &begin, &end, &density, &isGap); + while (accumPos > 0) { + + if (density > 0) { + /* convert (1 - maxDensity) to "color" number (224 - 0) */ + if (maxDensity == minDensity) { + col = minCol; + } else { + col = (Uint1) (minCol + (density - minDensity)*(maxCol - minCol)/(maxDensity - minDensity)); + } + color [2] = color [1] = color [0] = col; /* set to shade of grey. (minCol = 224) */ + AddAttribute (seg, COLOR_ATT, color, 0, 0, 1, 0); + AddRectangle (seg, begin, FPSP->ceiling - height, + end, FPSP->ceiling - height - (AIP->Height), NO_ARROW, TRUE, 0); + } + else if (isGap) { + AddAttribute (seg, COLOR_ATT, NULL, 0, 0, 1, 0); + AddLine (seg, begin, FPSP->ceiling - height - (AIP->Height)/2, + end, FPSP->ceiling - height - (AIP->Height)/2, NO_ARROW, 0); + } else { + /* put a small line above spaces between blocks we draw */ + if (0 < begin && end < vContext->seqLength) { /* ignore gaps at beginning and end of bioseq */ + ASSERT(!isGap && density == 0); + space_pixs = (end - begin)/vContext->viewScale; + /* if (3 <= space_pixs && space_pixs <= 10 && end < vContext->seqLength) { */ + if (space_pixs <= 20) { /* don't draw this line if it is more than 20 pixels long. */ + if (space_pixs < 3) { /* make sure bar is always at least 3 pixels long */ + int mid_point = end + begin; + end = (mid_point + 3 * vContext->viewScale) /2; + begin = (mid_point - 3 * vContext->viewScale) /2; + } + AddAttribute (seg, COLOR_ATT, NULL, 0, 0, 1, 0); + AddLine (seg, begin, FPSP->ceiling - height - (AIP->Height) - space_line_height - 1, + end - vContext->viewScale, FPSP->ceiling - height - (AIP->Height) - space_line_height - 1, NO_ARROW, 0); + } + } + } + accumPos = GetIntervalFromAccumulator(minusIAP, accumPos, &begin, &end, &density, &isGap); + } + AddAttribute (seg, COLOR_ATT, NULL, 0, 0, 1, 0); + AddTextLabel (seg, 0, FPSP->ceiling - height - (AIP->Height)/2, + "<", FIP->GroupLabelFont, 1, MIDDLE_LEFT, 0); + + height += space_line_height; + height += AIP->Height + FIP->IntraRowPaddingPixels; + } + +smearAlignmentsDone: + + FreeIntervalAccumulator(&plusIAP); + FreeIntervalAccumulator(&minusIAP); + + return height; } @@ -4867,7 +6269,8 @@ static Boolean FilterAndLayout ( */ for (SAnnP = BSP->annot; SAnnP != NULL; SAnnP = SAnnP->next) { - if (SAnnP->type != 2) continue; /* type 2 annotation is an alignment */ + if (SAnnP->type != 2) + continue; /* type 2 annotation is an alignment */ if (FP->GroupByAnnot) /* are we grouping by named annotations? */ { @@ -4882,22 +6285,25 @@ static Boolean FilterAndLayout ( emptyFilterGroup = FALSE; SAlnP = (SeqAlignPtr) SAnnP->data; + ResetFilterState (&FPS); - FPS.state.align.SAPhead = FPS.state.align.SAPcurrent = SAlnP; + if ( ! AlignmentFilterStateInit(SAlnP, BSP->id ,&FPS.state.align, vContext->extras)) + continue; - switch (layoutC) { + switch (layoutC) { case Layout_FeatTypePerLine: - height = SmearAlignments (&FPS, vContext); - height += FIP->IntraRowPaddingPixels; + height = SmearAlignments (&FPS, vContext); break; default: height = ProcessRows (layoutC, &FPS, vContext); break; } + AlignmentFilterStateFree(&FPS.state.align); + totalheight += height; if (height > 0) FPS.ceiling -= height; - } + } /* SAnnp, cycle through all SeqAnnots on this Bioseq */ height = 0; break; case FeatureFilter: @@ -5076,7 +6482,8 @@ NLM_EXTERN SegmenT CreateGraphicViewInternal ( SegmenT topLevel, AppearancePtr AP, FilterPtr FP, - LayoutAlgorithm overrideLayout + LayoutAlgorithm overrideLayout, + GraphicViewExtrasPtr extras ) { @@ -5109,6 +6516,7 @@ NLM_EXTERN SegmenT CreateGraphicViewInternal ( VC.FltPtr = FP; VC.overrideLayout = overrideLayout; VC.seqLength = bsp->length; + VC.extras = extras; if (NULL == ceiling) VC.ceiling = &theCeiling; @@ -5137,7 +6545,8 @@ NLM_EXTERN SegmenT CreateGraphicViewFromBsp ( SegmenT topLevel, AppearancePtr AP, FilterPtr FP, - LayoutAlgorithm overrideLayout + LayoutAlgorithm overrideLayout, + GraphicViewExtrasPtr extras ) { @@ -5180,7 +6589,7 @@ NLM_EXTERN SegmenT CreateGraphicViewFromBsp ( } RFP = CollectFeatures (bsp); if (RFP == NULL) return NULL; - seg = CreateGraphicViewInternal (bsp, from, to, allFeatures, RFP, scale, ceiling, topLevel, AP, FP, overrideLayout); + seg = CreateGraphicViewInternal (bsp, from, to, allFeatures, RFP, scale, ceiling, topLevel, AP, FP, overrideLayout, extras); FreeCollectedFeatures (RFP); return seg; } @@ -5191,7 +6600,8 @@ NLM_EXTERN SegmenT CreateGraphicView ( Int4 scale, CharPtr styleName, CharPtr filterName, - CharPtr overrideLayoutName + CharPtr overrideLayoutName, + GraphicViewExtrasPtr extras ) { @@ -5212,7 +6622,8 @@ NLM_EXTERN SegmenT CreateGraphicView ( } else { overrideLayout = Layout_Inherit; } - return CreateGraphicViewFromBsp (bsp, location, scale, NULL, NULL, AP, FP, overrideLayout); + + return CreateGraphicViewFromBsp (bsp, location, scale, NULL, NULL, AP, FP, overrideLayout, extras); } NLM_EXTERN Uint2 GetAppearanceCount (void) @@ -5241,6 +6652,16 @@ NLM_EXTERN Uint2 GetLayoutCount (void) return DIM (LayoutStrings); } +NLM_EXTERN Uint2 GetAlnScoreCount (void) +{ + return DIM (AlnScoreStrings); +} + +NLM_EXTERN Uint2 GetAlnScoreCutoffCount (void) +{ + return DIM (AlnScoreCutoffStrings); +} + NLM_EXTERN CharPtr PNTR GetStyleNameList (void) { @@ -5261,6 +6682,16 @@ NLM_EXTERN CharPtr PNTR GetFilterNameList (void) return VCP->FilterNameArray; } +NLM_EXTERN CharPtr PNTR GetAlnScoreNameList(void) +{ + return AlnScoreStrings; +} + +NLM_EXTERN CharPtr PNTR GetAlnScoreCutoffList(void) +{ + return AlnScoreCutoffStrings; +} + NLM_EXTERN CharPtr PNTR GetLayoutNameList (void) { @@ -5413,6 +6844,7 @@ static ConfigFileLine defaultStyleLines12 [] = { {"showtype", "no"}, {"showcontent", "yes"}, {"format", "accession"}, + {"displaywith", "outlinebox"}, {NULL, NULL} }; @@ -5490,6 +6922,7 @@ static ConfigFileLine defaultStyleLines19 [] = { {"showtype", "no"}, {"showcontent", "yes"}, {"format", "accession"}, + {"displaywith", "outlinebox"}, {NULL, NULL} }; diff --git a/desktop/asn2graphic.h b/desktop/asn2graphic.h index 8a980792..b4eac60d 100644 --- a/desktop/asn2graphic.h +++ b/desktop/asn2graphic.h @@ -29,7 +29,7 @@ * * Version Creation Date: 11/8/01 * -* $Revision: 6.7 $ +* $Revision: 6.8 $ * * File Description: * @@ -58,19 +58,27 @@ extern "C" { #endif +typedef struct graphicViewExtras { + CharPtr alignScoreName; + CharPtr alignScoreCutoff; +} GraphicViewExtras, PNTR GraphicViewExtrasPtr; + NLM_EXTERN SegmenT CreateGraphicView ( BioseqPtr bsp, SeqLocPtr location, Int4 scale, CharPtr styleName, CharPtr filterName, - CharPtr overrideLayout + CharPtr overrideLayout, + GraphicViewExtrasPtr extras ); /* These return a NULL-Pointer-terminated array of CharPtrs parsed from the configuration file */ NLM_EXTERN CharPtr PNTR GetStyleNameList (void); NLM_EXTERN CharPtr PNTR GetFilterNameList (void); +NLM_EXTERN CharPtr PNTR GetAlnScoreNameList (void); +NLM_EXTERN CharPtr PNTR GetAlnScoreCutoffList (void); NLM_EXTERN CharPtr PNTR GetLayoutNameList (void); diff --git a/desktop/asn2graphicp.h b/desktop/asn2graphicp.h index 862802a5..41a3c8b8 100644 --- a/desktop/asn2graphicp.h +++ b/desktop/asn2graphicp.h @@ -29,7 +29,7 @@ * * Version Creation Date: 11/8/01 * -* $Revision: 6.37 $ +* $Revision: 6.40 $ * * File Description: * @@ -227,7 +227,7 @@ typedef enum endPointType { typedef struct relevantFeatureItem { Int4 Left, Right; - Boolean plusstrand; + Uint1 featstrand; EndPointType LeftEnd; EndPointType RightEnd; CharPtr ContentLabel; @@ -236,6 +236,7 @@ typedef struct relevantFeatureItem { Int2 numivals; Uint2 entityID, itemType; Uint4 itemID; + Uint1 circularSpanningOrigin; /* on a bioseq w/ Circular topology, this feature crosses the origin */ SeqAnnotPtr sap; /* was this feature found in a named SeqAnnot table? 0 if not, else a pointer to the SeqAnnot */ } RelevantFeatureItem, PNTR RelevantFeatureItemPtr; @@ -281,7 +282,8 @@ NLM_EXTERN SegmenT CreateGraphicViewFromBsp ( SegmenT topLevel, AppearancePtr AP, FilterPtr FP, - LayoutAlgorithm overrideLayout + LayoutAlgorithm overrideLayout, + GraphicViewExtrasPtr extras ); /* If the same Bioseq will be rendered multiple times, it will be more efficient to use these functions */ @@ -297,7 +299,8 @@ NLM_EXTERN SegmenT CreateGraphicViewInternal ( SegmenT topLevel, AppearancePtr AP, FilterPtr FP, - LayoutAlgorithm overrideLayout + LayoutAlgorithm overrideLayout, + GraphicViewExtrasPtr extras ); NLM_EXTERN RelevantFeaturesPtr CollectFeatures (BioseqPtr bsp); @@ -322,6 +325,8 @@ NLM_EXTERN void AddAppearanceItemToAppearance (AppearanceItemPtr AIP, Appearance NLM_EXTERN Uint2 GetAppearanceCount (void); NLM_EXTERN Uint2 GetFilterCount (void); NLM_EXTERN Uint2 GetLayoutCount (void); +NLM_EXTERN Uint2 GetAlnScoreCount (void); +NLM_EXTERN Uint2 GetAlnScoreCutoffCount (void); #ifdef __cplusplus diff --git a/desktop/biosrc.c b/desktop/biosrc.c index 1d9174a7..5483b797 100644 --- a/desktop/biosrc.c +++ b/desktop/biosrc.c @@ -29,7 +29,7 @@ * * Version Creation Date: 1/22/95 * -* $Revision: 6.39 $ +* $Revision: 6.42 $ * * File Description: * @@ -220,6 +220,7 @@ typedef struct genbiopage { TexT orgcomment; DialoG subsource; TexT subcomment; + ButtoN add_type_strain_to_subcomment; TexT lineage; TexT gbDiv; DialoG db; @@ -984,6 +985,63 @@ static CharPtr MergeValNodeStrings (ValNodePtr list) return ptr; } +static void AddTypeStrainButtonProc (ButtoN b) +{ + GenBioPagePtr gbp; + CharPtr old_subcomment; + Int4 old_subcomment_len; + CharPtr org_name; + Int4 org_name_len; + const CharPtr ts = "type strain of "; + const CharPtr sep = "; "; + CharPtr new_subcomment; + + gbp = GetObjectExtra(b); + if (gbp == NULL) return; + old_subcomment_len = TextLength (gbp->subcomment) + 1; + old_subcomment = MemNew (old_subcomment_len + 1); + if (old_subcomment == NULL) return; + org_name_len = TextLength (gbp->taxName) + 1; + org_name = MemNew (org_name_len + 1); + if (org_name == NULL) + { + MemFree (old_subcomment); + return; + } + new_subcomment = MemNew (old_subcomment_len + + StringLen (sep) + + StringLen (ts) + + org_name_len + + 1); + if (new_subcomment == NULL) + { + MemFree (old_subcomment); + MemFree (org_name); + } + + GetTitle (gbp->subcomment, old_subcomment, old_subcomment_len); + TrimSpacesAroundString (old_subcomment); + GetTitle (gbp->taxName, org_name, org_name_len); + TrimSpacesAroundString (org_name); + if (old_subcomment[0] != 0) + { + StringCpy(new_subcomment, old_subcomment); + StringCat(new_subcomment, sep); + } + else + { + new_subcomment[0] = 0; + } + + StringCat (new_subcomment, ts); + StringCat (new_subcomment, org_name); + SetTitle (gbp->subcomment, new_subcomment); + MemFree (org_name); + MemFree (old_subcomment); + MemFree (new_subcomment); + Disable (b); +} + static Char useGenomicText [] = "\ (Use 'Genomic' for a sequence encoded by a nuclear gene.)\n"; @@ -1098,6 +1156,10 @@ static void BioSourcePtrToGenBioPage (DialoG d, Pointer data) if (head != NULL) { str = MergeValNodeStrings (head); SetTitle (gbp->subcomment, str); + if ( StringStr (str, "type strain of ")) + { + Disable (gbp->add_type_strain_to_subcomment); + } MemFree (str); } ValNodeFree (head); @@ -1369,6 +1431,17 @@ static Pointer GenBioPageToBioSourcePtr (DialoG d) ssp->name = SaveStringFromTextAndStripNewlines (gbp->subcomment); } } + /* look for plasmid-name - if we find one, set the location to plasmid */ + tmpssp = biop->subtype; + while (tmpssp != NULL) + { + if (tmpssp->subtype == SUBSRC_plasmid_name) { + biop->genome = GENOME_plasmid; + break; + } + tmpssp = tmpssp->next; + } + if (orp != NULL) { if (orp->taxname == NULL && orp->common == NULL && orp->mod == NULL && orp->db == NULL && orp->syn == NULL && @@ -1907,7 +1980,7 @@ static DialoG CreateBioSourceDialog (GrouP h, CharPtr title, GrouP PNTR pages, { ButtoN b; GrouP c; - GrouP f, f1, f2, f3; + GrouP f, f1, f2, f3, f4; GrouP g; GenBioPagePtr gbp; Int2 height; @@ -2103,7 +2176,10 @@ static DialoG CreateBioSourceDialog (GrouP h, CharPtr title, GrouP PNTR pages, x = MultiLinePrompt (f2, "Additional Source Information", max, programFont); gbp->subcomment = ScrollText (f2, 20, 3, programFont, TRUE, NULL); AlignObjects (ALIGN_MIDDLE, (HANDLE) x, (HANDLE) gbp->subcomment, NULL); - AlignObjects (ALIGN_CENTER, (HANDLE) gbp->subsource, (HANDLE) f2, NULL); + f4 = HiddenGroup (g, 1, 0, NULL); + gbp->add_type_strain_to_subcomment = PushButton (f4, "Add type strain to comment", AddTypeStrainButtonProc); + SetObjectExtra (gbp->add_type_strain_to_subcomment, gbp, NULL); + AlignObjects (ALIGN_CENTER, (HANDLE) gbp->subsource, (HANDLE) f2, (HANDLE) f4, NULL); gbp->modGrp [1] = HiddenGroup (k, -1, 0, NULL); SetGroupSpacing (gbp->modGrp [1], 10, 10); diff --git a/desktop/bspview.c b/desktop/bspview.c index 630a5749..016f2585 100644 --- a/desktop/bspview.c +++ b/desktop/bspview.c @@ -29,7 +29,7 @@ * * Version Creation Date: 4/30/95 * -* $Revision: 6.111 $ +* $Revision: 6.117 $ * * File Description: * @@ -444,8 +444,10 @@ static Boolean LaunchSequenceViewer (SeqIdPtr sip, BioseqPtr query) SeqViewProcsPtr svpp; if (sip == NULL) return FALSE; + SeqEntrySetScope (NULL); bsp = BioseqLockById (sip); if (bsp == NULL) return FALSE; + SeqEntrySetScope (NULL); entityID = BioseqFindEntity (sip, &itemID); if (entityID == 0) return FALSE; WatchCursor (); @@ -1906,8 +1908,11 @@ extern void SetBioseqViewTarget (BaseFormPtr fp, CharPtr seqId) { EnumFieldAssocPtr ap; BioseqViewFormPtr bfp; + BioseqPtr bsp; CharPtr ptr; + SeqIdPtr sip; Char str [128]; + Char tmp [128]; Boolean tryJustAccn = TRUE; Int2 val; @@ -1936,6 +1941,27 @@ extern void SetBioseqViewTarget (BaseFormPtr fp, CharPtr seqId) } } } + /* try local ID */ + sip = MakeSeqID (seqId); + bsp = BioseqFind (sip); + SeqIdFree (sip); + if (bsp == NULL) return; + sip = SeqIdFindWorst (bsp->id); + SeqIdWrite (sip, tmp, PRINTID_REPORT, sizeof (tmp)); + seqId = StringChr (tmp, '|'); + if (seqId == NULL) { + seqId = tmp; + } else { + seqId++; + } + for (ap = bfp->targetAlist, val = 1; ap != NULL && ap->name != NULL; ap++, val++) { + StringNCpy (str, ap->name, sizeof (str)); + if (StringICmp (str, seqId) == 0) { + SetValue (bfp->targetControl, val); + ChangeTarget ((Handle) bfp->targetControl); + return; + } + } } extern BioseqViewPtr GetBioseqViewPtrFromBaseFormPtr (BaseFormPtr fp) @@ -2559,6 +2585,7 @@ static ForM LIBCALL CreateNewSeqEntryViewFormEx (Int2 left, Int2 top, CharPtr ti GrouP h; Boolean hasAlignments; Int2 i; + Boolean is_nc = FALSE; Int2 j; GrouP k; Int4 length; @@ -2581,8 +2608,10 @@ static ForM LIBCALL CreateNewSeqEntryViewFormEx (Int2 left, Int2 top, CharPtr ti RecT r3; GrouP s; SeqEntryPtr sep; + SeqIdPtr sip; CharPtr str; CharPtr styleName; + TextSeqIdPtr tsip; Int4 val; WindoW w; PopuP x; @@ -2614,6 +2643,14 @@ static ForM LIBCALL CreateNewSeqEntryViewFormEx (Int2 left, Int2 top, CharPtr ti bfp->this_itemtype = OBJ_BIOSEQ; if (bsp != NULL) { bfp->this_subtype = bsp->repr; + for (sip = bsp->id; sip != NULL; sip = sip->next) { + if (sip->choice != SEQID_OTHER) continue; + tsip = (TextSeqIdPtr) sip->data.ptrvalue; + if (tsip == NULL) continue; + if (StringNCmp (tsip->accession, "NC_", 3) == 0) { + is_nc = TRUE; + } + } } else { bfp->this_subtype = Seq_repr_raw; } @@ -2765,13 +2802,20 @@ static ForM LIBCALL CreateNewSeqEntryViewFormEx (Int2 left, Int2 top, CharPtr ti if (svpp->initGenomeLabel != NULL) { bpp = bfp->bioseqNucPageList; str = svpp->initGenomeLabel; + if (is_nc) { + str = "GenBank"; + } } } else { if (svpp->initNucLabel != NULL) { bpp = bfp->bioseqNucPageList; str = svpp->initNucLabel; if (bsp->length > 350000) { - str = "Graphic"; + if (is_nc) { + str = "GenBank"; + } else { + str = "Graphic"; + } } } } @@ -2909,7 +2953,7 @@ static ForM LIBCALL CreateNewSeqEntryViewFormEx (Int2 left, Int2 top, CharPtr ti z = PushButton (bfp->bvd.findGeneGrp, "Find by Gene or Product", ShowGeneList); SetObjectExtra (z, (Pointer) &(bfp->bvd), NULL); - bfp->bvd.newGphControlGrp = HiddenGroup (h, -8, 0, NULL); + bfp->bvd.newGphControlGrp = HiddenGroup (h, -6, 0, NULL); #ifdef NEW_GRAPHICAL_VIEWER newGraphicalViewer = TRUE; @@ -2947,6 +2991,21 @@ static ForM LIBCALL CreateNewSeqEntryViewFormEx (Int2 left, Int2 top, CharPtr ti StaticPrompt (bfp->bvd.newGphControlGrp, "Scale", 0, popupMenuHeight, programFont, 'l'); bfp->bvd.newGphScale = PopupList (bfp->bvd.newGphControlGrp, TRUE, ChangeNewScale); SetObjectExtra (bfp->bvd.newGphScale, bfp, NULL); + + if (GetAppProperty("GPHVIEWSCOREALIGNS") != NULL) { + /* + StaticPrompt (bfp->bvd.newGphControlGrp, "Alignments: Score Type", 0, popupMenuHeight, programFont, 'l'); + bfp->bvd.newGphAlnScore = PopupList (bfp->bvd.newGphControlGrp, TRUE, ChangeNewFilter); + SetObjectExtra (bfp->bvd.newGphAlnScore, bfp, NULL); + PopupItems (bfp->bvd.newGphAlnScore, GetAlnScoreNameList ()); + SetValue (bfp->bvd.newGphAlnScore, 1); + */ + StaticPrompt (bfp->bvd.newGphControlGrp, "Alignments: Score Cutoff", 0, popupMenuHeight, programFont, 'l'); + bfp->bvd.newGphAlnCutoff = PopupList (bfp->bvd.newGphControlGrp, TRUE, ChangeNewFilter); + SetObjectExtra (bfp->bvd.newGphAlnCutoff, bfp, NULL); + PopupItems (bfp->bvd.newGphAlnCutoff, GetAlnScoreCutoffList ()); + SetValue (bfp->bvd.newGphAlnCutoff, 1); + } } Hide (bfp->bvd.styleControlGrp); diff --git a/desktop/bspview.h b/desktop/bspview.h index 2e259f76..e06df978 100644 --- a/desktop/bspview.h +++ b/desktop/bspview.h @@ -29,7 +29,7 @@ * * Version Creation Date: 4/30/95 * -* $Revision: 6.48 $ +* $Revision: 6.50 $ * * File Description: * @@ -100,7 +100,7 @@ typedef struct bioseqviewdata { PopuP newNumControl; PopuP newGridControl; - // for new sequence and alignment viewers + /* for new sequence and alignment viewers */ Int4 LineHeight, LineSpace, CharHeight, CharWidth, BlocksAtLine, CharsAtLine, TotalLines, TargetRow; Int2 SeqStartPosX; /* Draw Sequence from this x pos */ SeqAlignPtr salp; @@ -144,6 +144,8 @@ typedef struct bioseqviewdata { PopuP newGphStyle; PopuP newGphFilter; PopuP newGphScale; + PopuP newGphAlnScore; + PopuP newGphAlnCutoff; ChoicE newGphLayout; ValNodePtr slp_list; diff --git a/desktop/cdrgn.c b/desktop/cdrgn.c index c119779e..f30c029e 100644 --- a/desktop/cdrgn.c +++ b/desktop/cdrgn.c @@ -29,7 +29,7 @@ * * Version Creation Date: 1/22/95 * -* $Revision: 6.53 $ +* $Revision: 6.55 $ * * File Description: * @@ -56,6 +56,7 @@ #include <toasn3.h> #include <subutil.h> #include <explore.h> +#include <pmfapi.h> #define CODING_REGION_PAGE 0 #define GENE_PAGE 0 @@ -1925,6 +1926,249 @@ static void ConvMiscFeatWarn (ButtoN b) } } +static Int4 AccessionToGi (CharPtr string) +{ + /* + CharPtr str; + LinkSetPtr lsp; + Int4 gi; + + str = MemNew (StringLen (string) + 10); + sprintf (str, "\"%s\" [ACCN]", string); + lsp = EntrezTLEvalString (str, TYP_NT, -1, NULL, NULL); + MemFree (str); + if (lsp == NULL) return 0; + if (lsp->num <= 0) { + LinkSetFree (lsp); + return 0; + } + gi = lsp->uids [0]; + LinkSetFree (lsp); + return gi; + */ + Int4 gi; + SeqIdPtr sip; + + sip = SeqIdFromAccessionDotVersion (string); + if (sip == NULL) return 0; + gi = GetGIForSeqId (sip); + SeqIdFree (sip); + return gi; +} + +static void SetGeneAndProtFields (CdRgnFormPtr cfp, CharPtr title); + +static BioseqPtr GetProteinFromSep (SeqEntryPtr sep) +{ + BioseqPtr query_bsp; + + query_bsp = NULL; + SeqEntryExplore(sep, &query_bsp, FindProt); + return query_bsp; +} + +typedef struct proteinimportformdata { + CdRgnFormPtr cfp; + WindoW w; + TexT accession; + GrouP accntype; + ButtoN DownloadProtein; +} ProteinImportFormData, PNTR ProteinImportFormPtr; + +static void AddProteinToCDSDialog ( + BioseqPtr bsp, + CdRgnFormPtr cfp +) +{ + ValNodePtr vnp; + CharPtr vnpstr; + SeqLocPtr slp; + Char str [128]; + + PointerToDialog (cfp->protseq, bsp); + SetProteinLengthDisplay (cfp->protlen, bsp->length); + SeqIdWrite (bsp->id, str, PRINTID_REPORT, sizeof (str)); + SafeSetTitle (cfp->protSeqIdTxt, str); + if (bsp->descr != NULL) { + vnp = ValNodeFindNext (bsp->descr, NULL, Seq_descr_title); + if (vnp != NULL && vnp->data.ptrvalue != NULL) { + vnpstr = (CharPtr) vnp->data.ptrvalue; + SetGeneAndProtFields (cfp, vnpstr); + } + } + slp = DialogToPointer (cfp->location); + if (slp == NULL || (! cfp->locvisited)) { + DoPredictCdRegion (cfp); + } + SeqLocFree (slp); +} + +static void DownloadProteinFromEntrez (ButtoN b) +{ + SeqEntryPtr sep; + Int4 uid; + BioseqPtr bsp; + CdRgnFormPtr cfp; + Char str [128]; + ProteinImportFormPtr pif; + + pif = (ProteinImportFormPtr) GetObjectExtra (b); + if (pif == NULL) return; + cfp = pif->cfp; + if (cfp == NULL) return; + GetTitle (pif->accession, str, sizeof (str)); + if (StringHasNoText (str)) + { + return; + } + WatchCursor (); + if (GetValue (pif->accntype) == 1) { + uid = AccessionToGi (str); + } else { + if (! StrToLong (str, &uid)) { + uid = 0; + } + } + + if (uid > 0) { + sep = PubSeqSynchronousQuery (uid, 0, -1); + if (sep == NULL) { + Message (MSG_OK, "Unable to find this record in the database."); + return; + } + if (IS_Bioseq (sep)) { + } else if (IS_Bioseq_set (sep)) { + } else { + Message (MSG_OK, "Unable to find this record in the database."); + return; + } + } + bsp = GetProteinFromSep (sep); + if (bsp == NULL) + { + Message (MSG_ERROR, "No protein in record!"); + } + else + { + AddProteinToCDSDialog (bsp, cfp); + } + SeqEntryFree (sep); + Remove (pif->w); + ArrowCursor (); + Update (); +} + +static void FetchTextProc (TexT t) + +{ + Boolean alldigits; + Char ch; + ProteinImportFormPtr pif; + CharPtr ptr; + Char str [32]; + + pif = (ProteinImportFormPtr) GetObjectExtra (t); + if (pif == NULL) return; + GetTitle (t, str, sizeof (str)); + if (StringHasNoText (str)) { + SafeDisable (pif->DownloadProtein); + } else { + SafeEnable (pif->DownloadProtein); + TrimSpacesAroundString (str); + alldigits = TRUE; + ptr = str; + ch = *ptr; + while (ch != '\0') { + if (! IS_DIGIT (ch)) { + alldigits = FALSE; + } + ptr++; + ch = *ptr; + } + if (alldigits) { + SafeSetValue (pif->accntype, 2); + } else { + SafeSetValue (pif->accntype, 1); + } + } +} + +static void LoadFASTAProteinFromFile (ButtoN b) +{ + CdRgnFormPtr cfp; + CharPtr extension; + FILE * fp; + SeqEntryPtr sep; + BioseqPtr bsp; + Char path [PATH_MAX]; + ProteinImportFormPtr pif; + + pif = (ProteinImportFormPtr) GetObjectExtra (b); + if (pif == NULL) return; + cfp = pif->cfp; + if (cfp == NULL) return; + + path [0] = 0; + extension = GetAppProperty ("FastaProtExtension"); + if (GetInputFileName (path, sizeof (path), extension, "TEXT")) + { + fp = FileOpen (path, "r"); + if (fp != NULL) { + sep = FastaToSeqEntry (fp, FALSE); + if (sep != NULL && sep->choice == 1 && sep->data.ptrvalue != NULL) { + bsp = (BioseqPtr) sep->data.ptrvalue; + AddProteinToCDSDialog (bsp, cfp); + } + SeqEntryFree (sep); + } + FileClose (fp); + } + Remove (pif->w); +} + +static void ShowImportProteinDialog ( CdRgnFormPtr cfp) +{ + WindoW w; + GrouP c, f, g, h; + ButtoN b; + ProteinImportFormPtr pif; + + pif = (ProteinImportFormPtr) MemNew ( sizeof (ProteinImportFormData)); + if (pif == NULL) return; + pif->cfp = cfp; + w = FixedWindow (-50, -33, -10, -10, "Import Protein", StdCloseWindowProc); + pif->w = w; + SetObjectExtra (w, pif, NULL); + + h = HiddenGroup (w, -1, 0, NULL); + SetGroupSpacing (h, 10, 10); + + g = HiddenGroup (h, 4, 0, NULL); + + pif->accntype = HiddenGroup (g, 4, 0, NULL); + RadioButton (pif->accntype, "Accession"); + RadioButton (pif->accntype, "GI"); + SetValue (pif->accntype, 1); + pif->accession = DialogText (g, "", 6, FetchTextProc); + SetObjectExtra (pif->accession, pif, NULL); + pif->DownloadProtein = PushButton (g, "Download Protein From Entrez", + DownloadProteinFromEntrez); + SetObjectExtra (pif->DownloadProtein, pif, NULL); + Disable (pif->DownloadProtein); + + f = HiddenGroup (h, 4, 0, NULL); + b = PushButton (f, "Load FASTA Protein From File", LoadFASTAProteinFromFile); + SetObjectExtra (b, pif, NULL); + + c = HiddenGroup (w, 2, 0, NULL); + PushButton (c, "Cancel", StdCancelButtonProc); + AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) f, (HANDLE) c, NULL); + RealizeWindow (w); + Show (w); + Update (); + +} + static DialoG CreateCdRgnDialog (GrouP h, CharPtr title, Int2 genCode, SeqFeatPtr sfp, CdRgnFormPtr cfp) @@ -2234,20 +2478,11 @@ static void SetGeneAndProtFields (CdRgnFormPtr cfp, CharPtr title) } } } - static Boolean ImportCdRgnForm (ForM f, CharPtr filename) { - BioseqPtr bsp; CdRgnFormPtr cfp; - CharPtr extension; - FILE *fp; Char path [PATH_MAX]; - SeqEntryPtr sep; - SeqLocPtr slp; - Char str [128]; - ValNodePtr vnp; - CharPtr vnpstr; path [0] = '\0'; StringNCpy_0 (path, filename, sizeof (path)); @@ -2255,34 +2490,7 @@ static Boolean ImportCdRgnForm (ForM f, CharPtr filename) if (cfp != NULL) { switch (cfp->currentPage) { case CODING_REGION_PAGE : - extension = GetAppProperty ("FastaProtExtension"); - if (path [0] != '\0' || GetInputFileName (path, sizeof (path), extension, "TEXT")) { - fp = FileOpen (path, "r"); - if (fp != NULL) { - sep = FastaToSeqEntry (fp, FALSE); - if (sep != NULL && sep->choice == 1 && sep->data.ptrvalue != NULL) { - bsp = (BioseqPtr) sep->data.ptrvalue; - PointerToDialog (cfp->protseq, bsp); - SetProteinLengthDisplay (cfp->protlen, bsp->length); - SeqIdWrite (bsp->id, str, PRINTID_REPORT, sizeof (str)); - SafeSetTitle (cfp->protSeqIdTxt, str); - if (bsp->descr != NULL) { - vnp = ValNodeFindNext (bsp->descr, NULL, Seq_descr_title); - if (vnp != NULL && vnp->data.ptrvalue != NULL) { - vnpstr = (CharPtr) vnp->data.ptrvalue; - SetGeneAndProtFields (cfp, vnpstr); - } - } - slp = DialogToPointer (cfp->location); - if (slp == NULL || (! cfp->locvisited)) { - DoPredictCdRegion (cfp); - } - SeqLocFree (slp); - } - SeqEntryFree (sep); - } - FileClose (fp); - } + ShowImportProteinDialog ( cfp); break; case COMMON_PAGE : break; @@ -4666,8 +4874,12 @@ static void RnaRefPtrToRnaPage (DialoG d, Pointer data) shift = 2; } else { shift = 1; - } - i = aa - (64 + shift); + } + if (aa != '*') { + i = aa - (64 + shift); + } else { + i = 25; + } SetValue (rpp->AAitem, (Int2) i + 1); } head = NULL; @@ -4786,6 +4998,9 @@ static Pointer RnaPageToRnaRefPtr (DialoG d) shift = 1; } trna->aa = (Uint1) i + 64 + shift; + if (trna->aa == 91) { + trna->aa = (Uint1) '*'; + } } for (j = 0; j < 6; j++) { trna->codon [j] = 255; @@ -4996,7 +5211,12 @@ static void PopulateAAPopup (PopuP AAitem) str = (CharPtr) GetNameForResidue (sctp, i); sprintf (item, "%c %s", ch, str); PopupItem (AAitem, item); - } + } + i = '*'; + ch = GetSymbolForResidue (sctp, i); + str = (CharPtr) GetNameForResidue (sctp, i); + sprintf (item, "%c %s", ch, str); + PopupItem (AAitem, item); SetValue (AAitem, 1); } diff --git a/desktop/cdrgn.h b/desktop/cdrgn.h index d1d20ad2..e829550f 100644 --- a/desktop/cdrgn.h +++ b/desktop/cdrgn.h @@ -29,13 +29,19 @@ * * Version Creation Date: 1/22/95 * -* $Revision: 6.3 $ +* $Revision: 6.5 $ * * File Description: * * Modifications: * -------------------------------------------------------------------------- * $Log: cdrgn.h,v $ +* Revision 6.5 2003/10/23 16:43:56 kans +* changed operon to import feature +* +* Revision 6.4 2003/10/07 13:52:01 kans +* added gap, operon, oriT features and ecotype, estimated_length and operon qualifiers +* * Revision 6.3 2000/07/08 20:44:00 vakatov * Get all "#include" out of the 'extern "C" { }' scope; other cleanup... * diff --git a/desktop/dlgutil1.c b/desktop/dlgutil1.c index 6a171454..afa78016 100644 --- a/desktop/dlgutil1.c +++ b/desktop/dlgutil1.c @@ -29,7 +29,7 @@ * * Version Creation Date: 1/22/95 * -* $Revision: 6.38 $ +* $Revision: 6.40 $ * * File Description: * @@ -734,6 +734,7 @@ extern void SeqFeatPtrToCommon (FeatureFormPtr ffp, SeqFeatPtr sfp) SetTitle (ffp->exceptText, sfp->except_text); SetValue (ffp->useGeneXref, 1); SetTitle (ffp->geneSymbol, ""); + SetTitle (ffp->geneAllele, ""); SetTitle (ffp->geneDesc, ""); SetTitle (ffp->locusTag, ""); ggl.ffp = ffp; @@ -784,6 +785,7 @@ extern void SeqFeatPtrToCommon (FeatureFormPtr ffp, SeqFeatPtr sfp) SetValue (ffp->gene, 1); SetValue (ffp->useGeneXref, 3); SetTitle (ffp->geneSymbol, grp->locus); + SetTitle (ffp->geneAllele, grp->allele); SetTitle (ffp->geneDesc, grp->desc); SetTitle (ffp->locusTag, grp->locus_tag); SafeHide (ffp->editGeneBtn); @@ -792,6 +794,7 @@ extern void SeqFeatPtrToCommon (FeatureFormPtr ffp, SeqFeatPtr sfp) SetValue (ffp->gene, 2); SetValue (ffp->useGeneXref, 2); SetTitle (ffp->geneSymbol, grp->locus); + SetTitle (ffp->geneAllele, grp->allele); SetTitle (ffp->geneDesc, grp->desc); SetTitle (ffp->locusTag, grp->locus_tag); SafeHide (ffp->editGeneBtn); @@ -800,6 +803,7 @@ extern void SeqFeatPtrToCommon (FeatureFormPtr ffp, SeqFeatPtr sfp) SetValue (ffp->gene, 2); SetValue (ffp->useGeneXref, 2); SetTitle (ffp->geneSymbol, grp->locus); + SetTitle (ffp->geneAllele, grp->allele); SetTitle (ffp->geneDesc, grp->desc); SetTitle (ffp->locusTag, grp->locus_tag); SafeHide (ffp->editGeneBtn); @@ -832,6 +836,7 @@ extern void SeqFeatPtrToCommon (FeatureFormPtr ffp, SeqFeatPtr sfp) SetValue (ffp->gene, 1); SetValue (ffp->useGeneXref, 1); SetTitle (ffp->geneSymbol, ""); + SetTitle (ffp->geneAllele, ""); SetTitle (ffp->geneDesc, ""); SetTitle (ffp->locusTag, ""); PointerToDialog (ffp->featcits, NULL); @@ -973,6 +978,7 @@ static void AddProtRefXref (SeqFeatPtr sfp, TexT protXrefName) extern Boolean FeatFormReplaceWithoutUpdateProc (ForM f) { + Char allele [128]; MsgAnswer ans; BioseqPtr bsp; Char ch; @@ -1103,9 +1109,10 @@ extern Boolean FeatFormReplaceWithoutUpdateProc (ForM f) grp = GeneRefNew (); } else if (val == 2) { GetTitle (ffp->geneSymbol, symbol, sizeof (symbol)); + GetTitle (ffp->geneAllele, allele, sizeof (allele)); GetTitle (ffp->geneDesc, desc, sizeof (desc)); GetTitle (ffp->locusTag, locustag, sizeof (locustag)); - grp = CreateNewGeneRef (symbol, NULL, desc, FALSE); + grp = CreateNewGeneRef (symbol, allele, desc, FALSE); if (! StringHasNoText (locustag)) { if (grp == NULL) { grp = GeneRefNew (); @@ -1228,9 +1235,10 @@ extern Boolean FeatFormReplaceWithoutUpdateProc (ForM f) } if (sep != NULL && sep->data.ptrvalue != NULL) { GetTitle (ffp->geneSymbol, symbol, sizeof (symbol)); + GetTitle (ffp->geneAllele, allele, sizeof (allele)); GetTitle (ffp->geneDesc, desc, sizeof (desc)); GetTitle (ffp->locusTag, locustag, sizeof (locustag)); - grp = CreateNewGeneRef (symbol, NULL, desc, FALSE); + grp = CreateNewGeneRef (symbol, allele, desc, FALSE); if (! StringHasNoText (locustag)) { if (grp == NULL) { grp = GeneRefNew (); @@ -1750,6 +1758,9 @@ extern NameStdPtr AuthorSpreadsheetStringToNameStdPtr (CharPtr txt) suffix = GetEnumName (atoi(suffixVal), name_suffix_alist); nsp->names [5] = StringSave (suffix); TrimLeadingSpaces (nsp->names [5]); + if (StringHasNoText (nsp->names [5])) { + nsp->names [5] = MemFree (nsp->names [5]); + } } if (StringCmp (nsp->names [0], "et al") == 0) { nsp->names [0] = MemFree (nsp->names [0]); diff --git a/desktop/dlgutil2.c b/desktop/dlgutil2.c index 96912ab9..9e10333b 100644 --- a/desktop/dlgutil2.c +++ b/desktop/dlgutil2.c @@ -29,7 +29,7 @@ * * Version Creation Date: 1/22/95 * -* $Revision: 6.35 $ +* $Revision: 6.39 $ * * File Description: * @@ -935,6 +935,7 @@ static Boolean ShouldBeAGBQual (SeqFeatPtr sfp, Int2 qual, Boolean allowProductG return FALSE; } if (qual == GBQUAL_map && (sfp == NULL || sfp->idx.subtype != FEATDEF_repeat_region)) return FALSE; + if (qual == GBQUAL_operon && (sfp == NULL || sfp->idx.subtype != FEATDEF_operon)) return FALSE; if (Nlm_GetAppProperty ("SequinUseEMBLFeatures") == NULL) { if (qual == GBQUAL_usedin) { return FALSE; @@ -1127,6 +1128,12 @@ extern DialoG CreateImportFields (GrouP h, CharPtr name, SeqFeatPtr sfp, Boolean seen [qual] = LEGAL_FEATURE; } } + if (StringCmp (name, "repeat_region") == 0) { + seen [GBQUAL_map] = TRUE; + } + if (StringCmp (name, "operon") == 0) { + seen [GBQUAL_operon] = TRUE; + } for (i = 0; i < sefp->opt_num; i++) { qual = sefp->opt_qual [i]; if (qual > -1 && ShouldBeAGBQual (sfp, qual, allowProductGBQual)) { @@ -1268,6 +1275,10 @@ static void ChangeCannedMessage (PopuP p) SetTitle (ffp->exceptText, "nonconsensus splice site"); SetStatus (ffp->exception, TRUE); break; + case 8 : + SetTitle (ffp->exceptText, "rearrangement required for product"); + SetStatus (ffp->exception, TRUE); + break; default : break; } @@ -1403,6 +1414,7 @@ extern GrouP CreateCommonFeatureGroupEx (GrouP h, FeatureFormPtr ffp, PopupItem (canned, "trans splicing"); PopupItem (canned, "artificial frameshift"); PopupItem (canned, "nonconsensus splice site"); + PopupItem (canned, "rearrangement required"); if (sfp != NULL && sfp->excpt) { if (StringICmp (sfp->except_text, "RNA editing") == 0) { SetValue (canned, 2); @@ -1420,6 +1432,8 @@ extern GrouP CreateCommonFeatureGroupEx (GrouP h, FeatureFormPtr ffp, } else if (StringICmp (sfp->except_text, "non-consensus splice site") == 0 || StringICmp (sfp->except_text, "nonconsensus splice site") == 0) { SetValue (canned, 7); + } else if (StringICmp (sfp->except_text, "rearrangement required for product") == 0) { + SetValue (canned, 8); } } else { SetValue (canned, 1); @@ -1441,6 +1455,7 @@ extern GrouP CreateCommonFeatureGroupEx (GrouP h, FeatureFormPtr ffp, ffp->useGeneXref = NULL; ffp->newGeneGrp = NULL; ffp->geneSymbol = NULL; + ffp->geneAllele = NULL; ffp->geneDesc = NULL; ffp->locusTag = NULL; for (page = 0; page < 5; page++) { @@ -1476,6 +1491,8 @@ extern GrouP CreateCommonFeatureGroupEx (GrouP h, FeatureFormPtr ffp, ffp->newGeneGrp = HiddenGroup (y, 2, 0, NULL); StaticPrompt (ffp->newGeneGrp, "Gene Symbol", 0, dialogTextHeight, programFont, 'l'); ffp->geneSymbol = DialogText (ffp->newGeneGrp, "", 20, NULL); + StaticPrompt (ffp->newGeneGrp, "Allele", 0, dialogTextHeight, programFont, 'l'); + ffp->geneAllele = DialogText (ffp->newGeneGrp, "", 20, NULL); StaticPrompt (ffp->newGeneGrp, "Description", 0, dialogTextHeight, programFont, 'l'); ffp->geneDesc = DialogText (ffp->newGeneGrp, "", 20, NULL); StaticPrompt (ffp->newGeneGrp, "Locus Tag", 0, dialogTextHeight, programFont, 'l'); diff --git a/desktop/dlogutil.h b/desktop/dlogutil.h index e274ba92..367722e0 100644 --- a/desktop/dlogutil.h +++ b/desktop/dlogutil.h @@ -29,7 +29,7 @@ * * Version Creation Date: 1/22/95 * -* $Revision: 6.18 $ +* $Revision: 6.19 $ * * File Description: * @@ -100,6 +100,7 @@ extern ValNodePtr AddStringToValNodeChain (ValNodePtr head, CharPtr str, Uint1 c GrouP useGeneXref; \ GrouP newGeneGrp; \ TexT geneSymbol; \ + TexT geneAllele; \ TexT geneDesc; \ TexT locusTag; \ ButtoN editGeneBtn; \ diff --git a/desktop/dotvibrant.c b/desktop/dotvibrant.c index cf4ff2fd..dd72e96c 100644 --- a/desktop/dotvibrant.c +++ b/desktop/dotvibrant.c @@ -29,7 +29,7 @@ * * Version Creation Date: 8/8/01 * -* $Revision: 6.14 $ +* $Revision: 6.15 $ * * File Description: mouse management, graphic engine of the sequence viewer * part of this code is also used for the WWW Entrez viewer @@ -37,6 +37,9 @@ * Modifications: * -------------------------------------------------------------------------- * $Log: dotvibrant.c,v $ +* Revision 6.15 2003/05/05 12:34:47 rsmith +* type of DOTVibDataPtr displayOpts1 is Nlm_Handle, not HANDLE. Needed to compile under Codewarrior for Win32 +* * Revision 6.14 2002/08/07 18:14:23 kans * itemID is Uint4, minor cleanup * @@ -6526,7 +6529,7 @@ static void DOT_OpenSeqAnnotFile(IteM i) AlnMgr2IndexLite(sap); AlnMgr2SortAlnSetByNthRowPos(sap, 1); - Enable((HANDLE)vdp->displayOpts1); + Enable((Nlm_Handle)vdp->displayOpts1); if (vdp->alp){ /* discard previous alignment*/ vdp->alp->pict=NULL; DOT_ExitAlign(vdp->alp); @@ -6627,7 +6630,7 @@ NLM_EXTERN Boolean DOT_MakeMainViewer (DOTMainDataPtr mip, DOTAlignInfoPtr alp) #endif m2 = PulldownMenu (w, "Options"); vdp->displayOpts1=SubMenu(m2,"Display"); - if (!sap) Disable((HANDLE)vdp->displayOpts1); + if (!sap) Disable((Nlm_Handle)vdp->displayOpts1); vdp->displayOpts2=ChoiceGroup (vdp->displayOpts1, DOT_DisplayOptsProc); ChoiceItem (vdp->displayOpts2, "Dots ONLY"); ChoiceItem (vdp->displayOpts2, "Dots & Aligns"); diff --git a/desktop/e2docsum.c b/desktop/e2docsum.c index 289d8c06..8f502c81 100644 --- a/desktop/e2docsum.c +++ b/desktop/e2docsum.c @@ -29,7 +29,7 @@ * * Version Creation Date: 10/30/01 * -* $Revision: 6.41 $ +* $Revision: 6.46 $ * * File Description: * @@ -377,6 +377,34 @@ static Uint1 ncbisearchicon [] = { 0x40, 0x00, 0x00, 0x02, 0x7F, 0xFF, 0xFF, 0xFE }; +static Uint1 meshicon [] = { + 0x7F, 0xFF, 0xFF, 0xFE, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x7F, 0xFF, 0xFF, 0xFE +}; + +static Uint1 geneicon [] = { + 0x7F, 0xFF, 0xFF, 0xFE, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, + 0x40, 0x00, 0x00, 0x02, 0x7F, 0xFF, 0xFF, 0xFE +}; + static Uint1 genericon [] = { 0x7F, 0xFF, 0xFF, 0xFE, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, @@ -416,6 +444,8 @@ static CharPtr journalsRadios [] = { "Summary", "Fields", "Journals ID", NULL } static CharPtr unigeneRadios [] = { "Summary", "Fields", "UniGene ID", NULL }; static CharPtr pmcRadios [] = { "Summary", "Fields", "PMC ID", NULL }; static CharPtr ncbisearchRadios [] = { "Summary", "Fields", "Unique ID", NULL }; +static CharPtr meshRadios [] = { "Summary", "Fields", "MeSH ID", NULL }; +static CharPtr geneRadios [] = { "Summary", "Fields", "Gene ID", NULL }; static CharPtr localBioseqRadios [] = { "FASTA", NULL }; static CharPtr defaultLaunch [] = { "Web Entrez", NULL }; @@ -437,6 +467,8 @@ static CharPtr journalsLaunch [] = { "Web Entrez", NULL }; static CharPtr unigeneLaunch [] = { "Web Entrez", NULL }; static CharPtr pmcLaunch [] = { "Web Entrez", NULL }; static CharPtr ncbisearchLaunch [] = { "Web Entrez", NULL }; +static CharPtr meshLaunch [] = { "Web Entrez", NULL }; +static CharPtr geneLaunch [] = { "Web Entrez", NULL }; /*-----------------------------------*/ /* Data structures used to keep info */ @@ -738,6 +770,10 @@ static void DrawIcon (SummFormPtr sfp, RectPtr r, Int2 item, Int2 frst) icon = pmcicon; else if (StringICmp (dbName, "ncbisearch") == 0) icon = ncbisearchicon; + else if (StringICmp (dbName, "mesh") == 0) + icon = meshicon; + else if (StringICmp (dbName, "gene") == 0) + icon = geneicon; else icon = genericon; @@ -831,9 +867,13 @@ static CharPtr FormatDocsum (Entrez2DocsumPtr e2DocsumPtr) CharPtr marker; CharPtr mrnasrc1; CharPtr mrnasrc2; + CharPtr name; CharPtr oid; + CharPtr pdbacc; + CharPtr pdbdescr; CharPtr rank; CharPtr sciname; + CharPtr scopenote; CharPtr snpid; CharPtr str; CharPtr taxid; @@ -861,6 +901,8 @@ static CharPtr FormatDocsum (Entrez2DocsumPtr e2DocsumPtr) mrnasrc1 = NULL; mrnasrc2 = NULL; oid = NULL; + pdbacc = NULL; + pdbdescr = NULL; rank = NULL; sciname = NULL; taxid = NULL; @@ -870,7 +912,9 @@ static CharPtr FormatDocsum (Entrez2DocsumPtr e2DocsumPtr) dcsum = NULL; title = NULL; title1 = NULL; + name = NULL; description = NULL; + scopenote = NULL; for (e2DocsumDataPtr = e2DocsumPtr->docsum_data; e2DocsumDataPtr != NULL; e2DocsumDataPtr = e2DocsumDataPtr->next) { if (StringHasNoText (e2DocsumDataPtr->field_value)) continue; @@ -914,8 +958,16 @@ static CharPtr FormatDocsum (Entrez2DocsumPtr e2DocsumPtr) snpid = e2DocsumDataPtr->field_value; } else if (StringICmp (e2DocsumDataPtr->field_name, "DOCSUM") == 0) { dcsum = e2DocsumDataPtr->field_value; + } else if (StringICmp (e2DocsumDataPtr->field_name, "Name") == 0) { + name = e2DocsumDataPtr->field_value; } else if (StringICmp (e2DocsumDataPtr->field_name, "Description") == 0) { description = e2DocsumDataPtr->field_value; + } else if (StringICmp (e2DocsumDataPtr->field_name, "ScopeNote") == 0) { + scopenote = e2DocsumDataPtr->field_value; + } else if (StringICmp (e2DocsumDataPtr->field_name, "PdbAcc") == 0) { + pdbacc = e2DocsumDataPtr->field_value; + } else if (StringICmp (e2DocsumDataPtr->field_name, "PdbDescr") == 0) { + pdbdescr = e2DocsumDataPtr->field_value; } } @@ -951,6 +1003,13 @@ static CharPtr FormatDocsum (Entrez2DocsumPtr e2DocsumPtr) cpt = title; ttl = description; } + if (StringHasNoText (cpt) && (! StringHasNoText (name)) && (! StringHasNoText (description))) { + cpt = name; + ttl = description; + } + if (StringHasNoText (cpt)) { + cpt = pdbacc; + } if (StringHasNoText (cpt)) { sprintf (uidbuf, "%ld", uid); cpt = uidbuf; @@ -975,6 +1034,12 @@ static CharPtr FormatDocsum (Entrez2DocsumPtr e2DocsumPtr) ttl = dcsum; } if (StringHasNoText (ttl)) { + ttl = scopenote; + } + if (StringHasNoText (ttl)) { + ttl = pdbdescr; + } + if (StringHasNoText (ttl)) { ttl = "?"; } @@ -1068,6 +1133,7 @@ typedef CharPtr (*FormatE2DSPProc) (Entrez2DocsumPtr e2DocsumPtr); static CharPtr Query_FetchDocSumCommon (DoC d, Int2 item, FormatE2DSPProc proc) { + Int2 attributes; Entrez2RequestPtr e2RequestPtr = NULL; Entrez2ReplyPtr e2ReplyPtr; Entrez2DocsumDataPtr e2DocsumDataPtr; @@ -1113,9 +1179,11 @@ static CharPtr Query_FetchDocSumCommon (DoC d, Int2 item, FormatE2DSPProc proc) sfp->state [item - 1].hasAbstract = FALSE; for (e2DocsumDataPtr = e2DocsumPtr->docsum_data; e2DocsumDataPtr != NULL; e2DocsumDataPtr = e2DocsumDataPtr->next) { if (StringHasNoText (e2DocsumDataPtr->field_value)) continue; - if (StringICmp (e2DocsumDataPtr->field_name, "HasAbstract") == 0) { - if (StringICmp (e2DocsumDataPtr->field_value, "1") == 0) { - sfp->state [item - 1].hasAbstract = TRUE; + if (StringICmp (e2DocsumDataPtr->field_name, "Attributes") == 0) { + if (StrToInt (e2DocsumDataPtr->field_value, &attributes)) { + if ((attributes & 1) != 0) { + sfp->state [item - 1].hasAbstract = TRUE; + } } } } @@ -1187,9 +1255,11 @@ static CharPtr Query_FetchDocSumCommon (DoC d, Int2 item, FormatE2DSPProc proc) sfp->state [item - 1].hasAbstract = FALSE; for (e2DocsumDataPtr = e2DocsumPtr->docsum_data; e2DocsumDataPtr != NULL; e2DocsumDataPtr = e2DocsumDataPtr->next) { if (StringHasNoText (e2DocsumDataPtr->field_value)) continue; - if (StringICmp (e2DocsumDataPtr->field_name, "HasAbstract") == 0) { - if (StringICmp (e2DocsumDataPtr->field_value, "1") == 0) { - sfp->state [item - 1].hasAbstract = TRUE; + if (StringICmp (e2DocsumDataPtr->field_name, "Attributes") == 0) { + if (StrToInt (e2DocsumDataPtr->field_value, &attributes)) { + if ((attributes & 1) != 0) { + sfp->state [item - 1].hasAbstract = TRUE; + } } } } @@ -1767,6 +1837,10 @@ static void SetDocSumImportExportItems (SummFormPtr sfp) labels = pmcRadios; else if (StringICmp (dbName, "ncbisearch") == 0) labels = ncbisearchRadios; + else if (StringICmp (dbName, "mesh") == 0) + labels = meshRadios; + else if (StringICmp (dbName, "gene") == 0) + labels = geneRadios; else labels = defaultRadios; @@ -2053,6 +2127,8 @@ static DocPrntProc journalsDocProcs [] = { Query_FetchDocSum, Query_FetchFields, static DocPrntProc unigeneDocProcs [] = { Query_FetchDocSum, Query_FetchFields, FetchUid, NULL }; static DocPrntProc pmcDocProcs [] = { Query_FetchDocSum, Query_FetchFields, FetchUid, NULL }; static DocPrntProc ncbisearchDocProcs [] = { Query_FetchDocSum, Query_FetchFields, FetchUid, NULL }; +static DocPrntProc meshDocProcs [] = { Query_FetchDocSum, Query_FetchFields, FetchUid, NULL }; +static DocPrntProc geneDocProcs [] = { Query_FetchDocSum, Query_FetchFields, FetchUid, NULL }; static void RepopulateDocSum (SummFormPtr sfp, Boolean needToReset) @@ -2174,6 +2250,10 @@ static void RepopulateDocSum (SummFormPtr sfp, Boolean needToReset) retrieveProc = pmcDocProcs [val - 1]; else if (StringICmp (dbName, "ncbisearch") == 0) retrieveProc = ncbisearchDocProcs [val - 1]; + else if (StringICmp (dbName, "mesh") == 0) + retrieveProc = meshDocProcs [val - 1]; + else if (StringICmp (dbName, "gene") == 0) + retrieveProc = geneDocProcs [val - 1]; else retrieveProc = defaultDocProcs [val - 1]; @@ -3112,6 +3192,17 @@ NLM_EXTERN void LaunchRecViewer (ForM f, Int4 uid, Int2 numAlign, Int4Ptr alignu if (launchType == 1) { LaunchEntrezURL ("ncbisearch", uid, "DocSum"); } + } else if (StringICmp (dbName, "mesh") == 0) { + if (launchType == 1) { + LaunchEntrezURL ("mesh", uid, "DocSum"); + } + } else if (StringICmp (dbName, "gene") == 0) { + if (launchType == 1) { + LaunchEntrezURL ("gene", uid, "DocSum"); + } + } else { + /* default so new databases work without code changes */ + LaunchEntrezURL (dbName, uid, "DocSum"); } } } @@ -3685,6 +3776,10 @@ static Boolean ExportDocSumForm (ForM f, CharPtr filename) labels = pmcRadios; else if (StringICmp (dbName, "ncbisearch") == 0) labels = ncbisearchRadios; + else if (StringICmp (dbName, "mesh") == 0) + labels = meshRadios; + else if (StringICmp (dbName, "gene") == 0) + labels = geneRadios; else labels = defaultRadios; @@ -3755,6 +3850,12 @@ static Boolean ExportDocSumForm (ForM f, CharPtr filename) case 17: fprintf (fp, ">NCBISearch\n"); break; + case 18: + fprintf (fp, ">MeSH\n"); + break; + case 19: + fprintf (fp, ">Gene\n"); + break; default: fprintf (fp, ">?\n"); break; @@ -4898,6 +4999,10 @@ NLM_EXTERN ForM CreateDocsumForm ( labels = pmcRadios; else if (StringICmp (e2db->db_name, "ncbisearch") == 0) labels = ncbisearchRadios; + else if (StringICmp (e2db->db_name, "mesh") == 0) + labels = meshRadios; + else if (StringICmp (e2db->db_name, "gene") == 0) + labels = geneRadios; else labels = defaultRadios; @@ -4952,6 +5057,10 @@ NLM_EXTERN ForM CreateDocsumForm ( labels = pmcLaunch; else if (StringICmp (e2db->db_name, "ncbisearch") == 0) labels = ncbisearchLaunch; + else if (StringICmp (e2db->db_name, "mesh") == 0) + labels = meshLaunch; + else if (StringICmp (e2db->db_name, "gene") == 0) + labels = geneLaunch; else labels = defaultLaunch; @@ -5205,7 +5314,8 @@ static void AcceptNetConfigForm (ButtoN b) Update (); return; } else if (val == 3) { - SetAppParam ("NCBI", "NET_SERV", "SRV_CONN_MODE", "FIREWALL"); + SetAppParam ("NCBI", "NET_SERV", "SRV_CONN_MODE", "SERVICE"); + SetAppParam ("NCBI", "NET_SERV", "FIREWALL", "TRUE"); GetTitle (ncp->proxyHost, str, sizeof (str)); if (! StringHasNoText (str)) { SetAppParam ("NCBI", "NET_SERV", "SRV_HTTP_PROXY_HOST", str); @@ -5230,6 +5340,7 @@ static void AcceptNetConfigForm (ButtoN b) } } else { SetAppParam ("NCBI", "NET_SERV", "SRV_CONN_MODE", NULL); + SetAppParam ("NCBI", "NET_SERV", "FIREWALL", NULL); SetAppParam ("NCBI", "NET_SERV", "SRV_HTTP_PROXY_HOST", NULL); SetAppParam ("NCBI", "NET_SERV", "SRV_HTTP_PROXY_PORT", NULL); SetAppParam ("NCBI", "NET_SERV", "SRV_PROXY_HOST", NULL); @@ -5269,6 +5380,7 @@ static void AcceptNetConfigForm (ButtoN b) } if (NoEntryExists ("SRV_CONN_MODE") && + NoEntryExists ("FIREWALL") && NoEntryExists ("SRV_CONN_TIMEOUT") && NoEntryExists ("SRV_ENGINE_HOST") && NoEntryExists ("SRV_ENGINE_PORT") && @@ -5483,6 +5595,12 @@ NLM_EXTERN void ShowNewNetConfigForm ( } else if (GetAppParam ("NCBI", "NET_SERV", "SRV_CONN_MODE", "WWW", str, sizeof (str))) { if (StringICmp (str, "FIREWALL") == 0) { SafeSetValue (ncp->srvConnMode, 3); + } else if (StringICmp (str, "SERVICE") == 0) { + if (GetAppParam ("NCBI", "NET_SERV", "FIREWALL", "WWW", str, sizeof (str))) { + if (StringICmp (str, "TRUE") == 0) { + SafeSetValue (ncp->srvConnMode, 3); + } + } } } if (GetAppParam ("NCBI", "NET_SERV", "SRV_HTTP_PROXY_HOST", NULL, str, sizeof (str))) { diff --git a/desktop/gbfview.c b/desktop/gbfview.c index ac645006..c368cc39 100644 --- a/desktop/gbfview.c +++ b/desktop/gbfview.c @@ -29,7 +29,7 @@ * * Version Creation Date: 2/5/97 * -* $Revision: 6.67 $ +* $Revision: 6.70 $ * * File Description: * @@ -888,6 +888,7 @@ static void PopulateFlatFile (BioseqViewPtr bvp, FmtType format, FlgType flags) BioseqPtr bsp; CstType custom = 0; DoC doc; + Boolean doLockFarComponents = FALSE; Uint2 entityID; FonT fnt; FILE *fp; @@ -959,12 +960,26 @@ static void PopulateFlatFile (BioseqViewPtr bvp, FmtType format, FlgType flags) break; } } + + bsp = bvp->bsp; + entityID = ObjMgrGetEntityIDForPointer (bsp); + topsep = GetTopSeqEntryForEntityID (entityID); + LookForGEDetc (topsep, &isGED, &isNTorNW, &isNC, &isTPA); + if ((flags & SHOW_CONTIG_FEATURES) != 0 || (flags & SHOW_CONTIG_SOURCES) != 0) { - lockFar = TRUE; + if (isNTorNW || isTPA) { + lockFar = FALSE; + lookupFar = TRUE; + if (GetAppProperty ("InternalNcbiSequin") != NULL) { + doLockFarComponents = TRUE; + } + } else { + lockFar = TRUE; + } } if (bvp->hasTargetControl && bvp->ffCustomBtn != NULL) { if (GetStatus (bvp->ffCustomBtn)) { - custom = SHOW_TRANCRIPTION | SHOW_PEPTIDE; + custom |= SHOW_TRANCRIPTION | SHOW_PEPTIDE; } } doc = NULL; @@ -1001,11 +1016,16 @@ static void PopulateFlatFile (BioseqViewPtr bvp, FmtType format, FlgType flags) } svpp = (SeqViewProcsPtr) GetAppProperty ("SeqDisplayForm"); - if (svpp != NULL && svpp->lockFarComponents) { + if (svpp != NULL) { + if (svpp->lockFarComponents) { + doLockFarComponents = TRUE; + } + } + if (doLockFarComponents) { entityID = ObjMgrGetEntityIDForPointer (bsp); sep = GetTopSeqEntryForEntityID (entityID); if (bvp->bsplist == NULL && lockFar) { - bvp->bsplist = LockFarComponentsEx (sep, TRUE, FALSE, FALSE); + bvp->bsplist = LockFarComponentsEx (sep, TRUE, FALSE, FALSE, NULL); } if (lookupFar) { hastpaaligns = FALSE; @@ -1020,6 +1040,9 @@ static void PopulateFlatFile (BioseqViewPtr bvp, FmtType format, FlgType flags) if (bvp->viewWholeEntity) { sep = GetTopSeqEntryForEntityID (entityID); usethetop = sep; + if (format == FTABLE_FMT) { + custom |= SHOW_PROT_FTABLE; + } } else if (ISA_na (bsp->mol) && bsp->repr == Seq_repr_seg) { sep = GetBestTopParentForData (entityID, bsp); } else if (ISA_aa (bsp->mol) && bsp->repr == Seq_repr_seg) { @@ -1038,7 +1061,7 @@ static void PopulateFlatFile (BioseqViewPtr bvp, FmtType format, FlgType flags) WatchCursor (); ffColFmt.pixWidth = screenRect.right - screenRect.left; ffColFmt.pixInset = 8; - LookForGEDetc (topsep, &isGED, &isNTorNW, &isNC, &isTPA); + /* LookForGEDetc (topsep, &isGED, &isNTorNW, &isNC, &isTPA); */ if ((flags & SHOW_CONTIG_FEATURES) != 0 || (flags & SHOW_CONTIG_SOURCES) != 0) { if (isNTorNW || isTPA) { flags |= ONLY_NEAR_FEATURES; @@ -1186,7 +1209,7 @@ static void PopulateFasta (BioseqViewPtr bvp) entityID = ObjMgrGetEntityIDForPointer (bsp); sep = GetTopSeqEntryForEntityID (entityID); if (bvp->bsplist == NULL) { - bvp->bsplist = LockFarComponentsEx (sep, TRUE, FALSE, FALSE); + bvp->bsplist = LockFarComponentsEx (sep, TRUE, FALSE, FALSE, NULL); } } diff --git a/desktop/gphview.c b/desktop/gphview.c index 9c59d264..a3028aa5 100644 --- a/desktop/gphview.c +++ b/desktop/gphview.c @@ -29,7 +29,7 @@ * * Version Creation Date: 2/5/97 * -* $Revision: 6.59 $ +* $Revision: 6.62 $ * * File Description: * @@ -3839,7 +3839,7 @@ static void VisitAndDrawBioseqs ( if (state == NULL) return; CreateGraphicViewFromBsp (bsp, NULL, state->scale, &state->ceiling, state->topLevelSegment, state->AP, - state->FP, state->overrideLayout); + state->FP, state->overrideLayout, NULL); state->ceiling -= 25; } @@ -3875,6 +3875,10 @@ static void PopulateAsn2GphGraphic ( CharPtr appearanceName; CharPtr filterName; CharPtr layoutName; + CharPtr alignScoreName; + CharPtr alignScoreCutoff; + GraphicViewExtras gvExtras; + ViewerConfigsPtr myVCP; MultiBioseqDrawState drawState; @@ -3972,6 +3976,31 @@ static void PopulateAsn2GphGraphic ( layoutName = NULL; /* no need to pass a dummy string for an optional value */ } + MemSet ((Pointer) &gvExtras, 0, sizeof (GraphicViewExtras)); + if (GetAppProperty("GPHVIEWSCOREALIGNS") != NULL) { + /* + i = GetValue (bvp->newGphAlnScore) - 1; + nameList = GetAlnScoreNameList (); + if (i < GetAlnScoreCount ()) { + alignScoreName = nameList [i]; + } else { + alignScoreName = nameList[0]; + } + gvExtras.alignScoreName = alignScoreName; + */ + i = GetValue (bvp->newGphAlnCutoff) - 1; + nameList = GetAlnScoreCutoffList (); + if (i < GetAlnScoreCutoffCount ()) { + alignScoreCutoff = nameList [i]; + } else { + alignScoreCutoff = nameList[0]; + } + gvExtras.alignScoreCutoff = alignScoreCutoff; + } else { + gvExtras.alignScoreName = ""; + gvExtras.alignScoreCutoff = ""; + } + if (!bvp->viewWholeEntity) { sep = SeqMgrGetSeqEntryForData (bsp); entityID = ObjMgrGetEntityIDForChoice (sep); @@ -3996,10 +4025,10 @@ static void PopulateAsn2GphGraphic ( vn.choice = SEQLOC_INT; vn.data.ptrvalue = &si; - bvp->pict = CreateGraphicView (bsp, &vn, scaleX, appearanceName, filterName, layoutName); + bvp->pict = CreateGraphicView (bsp, &vn, scaleX, appearanceName, filterName, layoutName, &gvExtras); } #else - bvp->pict = CreateGraphicView (bsp, NULL, scaleX, appearanceName, filterName, layoutName); + bvp->pict = CreateGraphicView (bsp, NULL, scaleX, appearanceName, filterName, layoutName, &gvExtras); #endif if (entityID > 0) { diff --git a/desktop/import.c b/desktop/import.c index 39f9a7fe..1ddec94d 100644 --- a/desktop/import.c +++ b/desktop/import.c @@ -29,7 +29,7 @@ * * Version Creation Date: 6/18/95 * -* $Revision: 6.35 $ +* $Revision: 6.37 $ * * File Description: * @@ -107,7 +107,8 @@ extern EnumFieldAssocPtr import_featdef_alist (Boolean notJustImpFeats, Boolean subtype != FEATDEF_virion && subtype != FEATDEF_mutation && subtype != FEATDEF_allele && - subtype != FEATDEF_site_ref) { + subtype != FEATDEF_site_ref && + subtype != FEATDEF_gap) { if (allowPeptideFeats || (subtype != FEATDEF_mat_peptide && subtype != FEATDEF_sig_peptide && @@ -561,6 +562,7 @@ extern ForM CreateImportForm (Int2 left, Int2 top, CharPtr title, GrouP c; GrouP g; GrouP h; + Boolean hasGeneControl; ImprtFormPtr ifp; GrouP s; StdEditorProcsPtr sepp; @@ -649,7 +651,11 @@ extern ForM CreateImportForm (Int2 left, Int2 top, CharPtr title, importFormTabs [0] = NULL; s = HiddenGroup (h, -1, 0, NULL); - CreateCommonFeatureGroup (s, (FeatureFormPtr) ifp, sfp, TRUE, TRUE); + hasGeneControl = TRUE; + if (StringICmp (title, "operon") == 0) { + hasGeneControl = FALSE; + } + CreateCommonFeatureGroup (s, (FeatureFormPtr) ifp, sfp, hasGeneControl, TRUE); ifp->pages [COMMON_PAGE] = s; Hide (ifp->pages [COMMON_PAGE]); diff --git a/desktop/salogif.c b/desktop/salogif.c index 8eb30e82..dd913e65 100644 --- a/desktop/salogif.c +++ b/desktop/salogif.c @@ -1,4 +1,4 @@ -/* $RCSfile: salogif.c,v $ $Revision: 6.2 $ $Date: 2000/05/12 19:21:45 $ +/* $RCSfile: salogif.c,v $ $Revision: 6.3 $ $Date: 2003/07/15 14:36:31 $ * ========================================================================== * * PUBLIC DOMAIN NOTICE @@ -25,13 +25,16 @@ * * Author: Jinghui Zhang * -* $Revision: 6.2 $ +* $Revision: 6.3 $ * * File Description: * The Blast Search result visualization utilities * * -------------------------------------------------------------------------- * $Log: salogif.c,v $ +* Revision 6.3 2003/07/15 14:36:31 dondosha +* Added #defines for substitutes to fprintf and fflush, needed for gzip compression of Web BLAST results +* * Revision 6.2 2000/05/12 19:21:45 shavirin * Fixed memory leak in print_defline_for_sequence(). * @@ -72,6 +75,10 @@ #include <seqmgr.h> #include <salogif.h> +int (*gif_fprintf)(FILE*, const char *, ...) = fprintf; +int (*gif_fflush)(FILE*) = fflush; +#define fprintf gif_fprintf +#define fflush gif_fflush /******************************************************************* * STATIC diff --git a/desktop/salsa.c b/desktop/salsa.c index 57cd5544..9540fed9 100644 --- a/desktop/salsa.c +++ b/desktop/salsa.c @@ -28,7 +28,7 @@ * * Version Creation Date: 1/27/96 * -* $Revision: 6.158 $ +* $Revision: 6.159 $ * * File Description: * @@ -2728,7 +2728,8 @@ static void SalsaNewFeaturesMenu (MenU m, Boolean is_na) subtype != FEATDEF_virion && subtype != FEATDEF_mutation && subtype != FEATDEF_allele && - subtype != FEATDEF_site_ref) { + subtype != FEATDEF_site_ref && + subtype != FEATDEF_gap) { i = CommandItem (sub, ompp->proclabel, SalsaNewFeatureMenuProc); nfp = (NewFeaturePtr) MemNew (sizeof (NewFeatureData)); if (nfp != NULL) { diff --git a/desktop/seqpanel.c b/desktop/seqpanel.c index 6899f079..3ab050b8 100644 --- a/desktop/seqpanel.c +++ b/desktop/seqpanel.c @@ -1,4 +1,4 @@ -/* $Id: seqpanel.c,v 6.25 2003/03/31 17:06:33 lebedev Exp $ +/* $Id: seqpanel.c,v 6.26 2003/04/22 17:33:17 beloslyu Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE @@ -893,7 +893,7 @@ static void DrawFeature(Int2 x, Int2 y, Int4 line, Int4 row, Int2 itemID, DrawLineEx(x1+1, y-bvp->LineHeight/2-1, x2, y-bvp->LineHeight/2-1, 1); DrawLineEx(x1+1, y-bvp->LineHeight/2+7, x2, y-bvp->LineHeight/2+7, 1); } -#elif defined(WIN_MSWIN) // should be verified +#elif defined(WIN_MSWIN) /* should be verified */ DrawLineEx(x1+1, y-bvp->LineHeight/2+2, x2, y-bvp->LineHeight/2+2, 3); if (isSelected(itemID, bvp)) { Black(); diff --git a/desktop/seqsub.c b/desktop/seqsub.c index f2baf925..5fced3e9 100644 --- a/desktop/seqsub.c +++ b/desktop/seqsub.c @@ -29,7 +29,7 @@ * * Version Creation Date: 1/22/95 * -* $Revision: 6.9 $ +* $Revision: 6.11 $ * * File Description: * @@ -357,12 +357,58 @@ extern DialoG CreateContactDialog (GrouP h, CharPtr title) typedef struct citsubpage { DIALOG_MESSAGE_BLOCK DialoG authors; + TexT consortium; DialoG date; DialoG affil; TexT descr; GrouP citsubGrp [5]; } CitsubPage, PNTR CitsubPagePtr; +static AuthListPtr AddConsortiumToAuthList (AuthListPtr alp, TexT consortium) + +{ + AuthorPtr ap; + ValNodePtr names; + PersonIdPtr pid; + + if (TextHasNoText (consortium)) return alp; + if (alp == NULL) { + alp = AuthListNew (); + alp->choice = 1; + } + pid = PersonIdNew (); + if (pid == NULL) return NULL; + pid->choice = 5; + pid->data = SaveStringFromText (consortium); + ap = AuthorNew (); + if (ap == NULL) return NULL; + ap->name = pid; + names = ValNodeAdd (&(alp->names)); + names->choice = 1; + names->data.ptrvalue = ap; + return alp; +} + +static void AuthListToConsortium (AuthListPtr alp, TexT consortium) + +{ + AuthorPtr ap; + ValNodePtr names; + PersonIdPtr pid; + CharPtr str; + + if (alp == NULL || consortium == NULL) return; + if (alp->choice != 1) return; + for (names = alp->names; names != NULL; names = names->next) { + ap = names->data.ptrvalue; + if (ap == NULL) continue; + pid = ap->name; + if (pid == NULL || pid->choice != 5) continue; + str = (CharPtr) pid->data; + SafeSetTitle (consortium, str); + } +} + static void CitSubPtrToCitsubPage (DialoG d, Pointer data) { @@ -382,6 +428,7 @@ static void CitSubPtrToCitsubPage (DialoG d, Pointer data) if (csp != NULL) { alp = csp->authors; PointerToDialog (cpp->authors, (Pointer) alp); + AuthListToConsortium (alp, cpp->consortium); if (alp != NULL) { PointerToDialog (cpp->affil, alp->affil); } @@ -409,6 +456,7 @@ static Pointer CitsubPageToCitSubPtr (DialoG d) csp = CitSubNew (); if (csp != NULL) { alp = (AuthListPtr) DialogToPointer (cpp->authors); + alp = AddConsortiumToAuthList (alp, cpp->consortium); if (alp != NULL) { alp->affil = DialogToPointer (cpp->affil); } @@ -540,6 +588,7 @@ extern DialoG CreateCitSubDialog (GrouP h, CharPtr title, CitSubPtr csp) GrouP k; GrouP m; GrouP p; + GrouP q; GrouP s; DialoG tbs; @@ -583,6 +632,9 @@ extern DialoG CreateCitSubDialog (GrouP h, CharPtr title, CitSubPtr csp) cpp->citsubGrp [0] = HiddenGroup (k, -1, 0, NULL); cpp->authors = CreateAuthorDialog (cpp->citsubGrp [0], 3, -1); + q = HiddenGroup (cpp->citsubGrp [0], 2, 0, NULL); + StaticPrompt (q, "Consortium", 0, stdLineHeight, programFont, 'l'); + cpp->consortium = DialogText (q, "", 16, NULL); cpp->affil = CreateExtAffilDialog (k, NULL, &(cpp->citsubGrp [1]), @@ -598,8 +650,8 @@ extern DialoG CreateCitSubDialog (GrouP h, CharPtr title, CitSubPtr csp) Hide (cpp->citsubGrp [4]); AlignObjects (ALIGN_CENTER, (HANDLE) tbs, (HANDLE) cpp->authors, - (HANDLE) cpp->citsubGrp [3], (HANDLE) cpp->date, - (HANDLE) cpp->affil, NULL); + (HANDLE) q, (HANDLE) cpp->citsubGrp [3], + (HANDLE) cpp->date, (HANDLE) cpp->affil, NULL); } return (DialoG) p; @@ -722,6 +774,7 @@ static Pointer SubmitPageToSubmitBlockPtr (DialoG d) { Char ch; Int2 i; + CharPtr os; CharPtr ptr; SubmitBlockPtr sbp; CharPtr sequin_app_version; @@ -761,7 +814,12 @@ static Pointer SubmitPageToSubmitBlockPtr (DialoG d) if (StringHasNoText (spp->tool)) { sequin_app_version = (CharPtr) GetAppProperty ("SequinAppVersion"); if (sequin_app_version != NULL) { - sprintf (tmp, "Sequin %s", sequin_app_version); + os = GetOpSysString (); + if (os != NULL) { + sprintf (tmp, "Sequin %s - %s", sequin_app_version, os); + } else { + sprintf (tmp, "Sequin %s", sequin_app_version); + } } else { StringCpy (tmp, "Sequin"); } diff --git a/desktop/vsm.c b/desktop/vsm.c index 38989b6d..eabf5110 100644 --- a/desktop/vsm.c +++ b/desktop/vsm.c @@ -29,7 +29,7 @@ * * Version Creation Date: 11-29-94 * -* $Revision: 6.13 $ +* $Revision: 6.14 $ * * File Description: * @@ -705,7 +705,8 @@ Boolean LIBCALL VSMAddMenu (WindoW w, Int2 menutype) subtype != FEATDEF_virion && subtype != FEATDEF_mutation && subtype != FEATDEF_allele && - subtype != FEATDEF_site_ref) { + subtype != FEATDEF_site_ref && + subtype != FEATDEF_gap) { i = CommandItem (sub2, ompp->proclabel, VSeqMgrStdMenuProc); SetObjectExtra(i, (VoidPtr)ompp, NULL); ctr++; |