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

« back to all changes in this revision

Viewing changes to sequin/sequin8.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
*
30
30
* Version Creation Date:   2/3/98
31
31
*
32
 
* $Revision: 6.308 $
 
32
* $Revision: 6.356 $
33
33
*
34
34
* File Description: 
35
35
*
58
58
#include <spidey.h>
59
59
#include <blast.h>
60
60
#include <salpanel.h>
 
61
#include <edutil.h>
 
62
#include <asn2gnbp.h> /* included for discrepancy report */
 
63
 
61
64
 
62
65
#define DEFLINE_MAX_LEN          380
63
66
#define TEXT_MAX_LEN             64
319
322
  return code;
320
323
}
321
324
 
322
 
extern void ExtendSeqLocToEnd (SeqLocPtr slp, BioseqPtr bsp, Boolean end5)
323
 
{
324
 
  Uint1          strand;
325
 
  SeqLocPtr      slp_to_change, slp_index;
326
 
  Int4           extent_to_change;
327
 
  Int4           start, stop;
328
 
  SeqIdPtr       sip;
 
325
extern void ExtendSeqLocToPosition (SeqLocPtr slp, Boolean end5, Int4 pos)
 
326
{
 
327
  Uint1          strand;
 
328
  SeqLocPtr      slp_to_change, slp_index;
 
329
  Int4           extent_to_change;
 
330
  Int4           start, stop;
 
331
  SeqIdPtr       sip;
 
332
  BioseqPtr      bsp;
 
333
  
 
334
  if (slp == NULL || pos < 0) return;
 
335
  
 
336
  bsp = BioseqFindFromSeqLoc (slp);
 
337
  if (bsp == NULL) return;
 
338
 
 
339
  slp_to_change = NULL;
 
340
  strand = SeqLocStrand (slp);
 
341
  switch (slp->choice)
 
342
  {
 
343
    case SEQLOC_INT:
 
344
      slp_to_change = slp;
 
345
      break;
 
346
    case SEQLOC_MIX:
 
347
        case SEQLOC_PACKED_INT:
 
348
      sip = SeqLocId (slp);
 
349
      if (sip == NULL) return; /* can only process if all on one bioseq */
 
350
      slp_to_change = NULL;
 
351
      if ((strand == Seq_strand_minus && end5)
 
352
        || (strand != Seq_strand_minus && !end5))
 
353
      {
 
354
        extent_to_change = 0;
 
355
        for (slp_index = (SeqLocPtr)slp->data.ptrvalue; slp_index != NULL; slp_index = slp_index->next)
 
356
        {
 
357
          stop = GetOffsetInBioseq (slp_index, bsp, SEQLOC_STOP);
 
358
          if (stop > extent_to_change)
 
359
          {
 
360
            slp_to_change = slp_index;
 
361
            extent_to_change = stop;
 
362
          }
 
363
        }
 
364
      }
 
365
      else
 
366
      {
 
367
        extent_to_change = bsp->length;
 
368
        for (slp_index = (SeqLocPtr)slp->data.ptrvalue; slp_index != NULL; slp_index = slp_index->next)
 
369
        {
 
370
          start = GetOffsetInBioseq (slp_index, bsp, SEQLOC_START);
 
371
          if (start < extent_to_change)
 
372
          {
 
373
            slp_to_change = slp_index;
 
374
            extent_to_change = start;
 
375
          }
 
376
        }
 
377
      }
 
378
      break;
 
379
  }
 
380
 
 
381
  if (slp_to_change != NULL)
 
382
  {
 
383
    if ((strand == Seq_strand_minus && end5)
 
384
      || (strand != Seq_strand_minus && !end5))
 
385
    {
 
386
      start = GetOffsetInBioseq (slp_to_change, bsp, SEQLOC_START);
 
387
      stop = pos;
 
388
    }
 
389
    else
 
390
    {
 
391
      start = pos;
 
392
      stop = GetOffsetInBioseq (slp_to_change, bsp, SEQLOC_STOP);
 
393
    }
 
394
    if (start < 0 
 
395
        || stop > bsp->length - 1
 
396
        || start > stop)
 
397
    {
 
398
      return;
 
399
    }
 
400
    expand_seq_loc (start, stop, strand, slp_to_change);
 
401
  }
 
402
}
 
403
 
 
404
extern Int4 ExtendSeqLocToEnd (SeqLocPtr slp, BioseqPtr bsp, Boolean end5)
 
405
{
 
406
  Uint1          strand;
 
407
  SeqLocPtr      slp_to_change, slp_index;
 
408
  Int4           extent_to_change;
 
409
  Int4           start, stop;
 
410
  SeqIdPtr       sip;
 
411
  Int4           start_diff = 0;
329
412
  
330
413
  if (slp == NULL || bsp == NULL) return;
331
414
 
384
467
      start = 0;
385
468
      stop = GetOffsetInBioseq (slp_to_change, bsp, SEQLOC_STOP);
386
469
    }
 
470
    if (end5) {
 
471
        if (strand == Seq_strand_minus) {
 
472
            start_diff = bsp->length - 1 - GetOffsetInBioseq(slp_to_change, bsp, SEQLOC_START);
 
473
        } else {
 
474
            start_diff = GetOffsetInBioseq(slp_to_change, bsp, SEQLOC_START);
 
475
        }
 
476
    }
 
477
    
387
478
    expand_seq_loc (start, stop, strand, slp_to_change);
388
479
  }
 
480
  return start_diff;
389
481
}
390
482
 
391
483
static void ExtendOnePartialFeature (SeqFeatPtr sfp, Pointer userdata)
392
484
{
393
 
  BioseqPtr bsp;
394
 
  Boolean   partial3, partial5;
 
485
  BioseqPtr   bsp;
 
486
  Boolean     partial3, partial5;
 
487
  Int4        start_diff;
 
488
  CdRegionPtr crp;
395
489
 
396
490
  if (sfp == NULL) return;
397
491
  bsp = BioseqFindFromSeqLoc (sfp->location);
399
493
  CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
400
494
  if (partial5)
401
495
  {
402
 
    ExtendSeqLocToEnd (sfp->location, bsp, TRUE);
 
496
    start_diff = ExtendSeqLocToEnd (sfp->location, bsp, TRUE);
 
497
    if (start_diff > 0 && sfp->data.choice == SEQFEAT_CDREGION) {
 
498
      crp = (CdRegionPtr) sfp->data.value.ptrvalue;
 
499
      if (crp != NULL) {
 
500
          if (crp->frame == 0) {
 
501
              crp->frame = 1;
 
502
          }
 
503
          crp->frame = (crp->frame + start_diff - 1) % 3 + 1;
 
504
      }
 
505
    }
403
506
  }
404
507
  if (partial3)
405
508
  {
410
513
extern void ExtendPartialFeatures (IteM i)
411
514
{
412
515
  BaseFormPtr       bfp;
413
 
  SeqEntryPtr       sep;
 
516
  SeqEntryPtr       sep, old_scope;
414
517
  SelStructPtr      sel;
415
518
  SeqFeatPtr        sfp;
416
519
  SeqMgrFeatContext fcontext;
426
529
  sel = ObjMgrGetSelected ();
427
530
  WatchCursor ();
428
531
  Update ();
 
532
  old_scope = SeqEntrySetScope(sep);
429
533
  if (sel == NULL)
430
534
  {
431
535
    VisitFeaturesInSep (sep, NULL, ExtendOnePartialFeature);
446
550
      sel = sel->next;
447
551
    }
448
552
  }
 
553
  SeqEntrySetScope(old_scope);
449
554
  ArrowCursor ();
450
555
  Update ();
451
556
  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3852
3957
}
3853
3958
 
3854
3959
 
 
3960
 
 
3961
 
 
3962
 
 
3963
typedef struct genomeprojiduserdialog {
 
3964
  DIALOG_MESSAGE_BLOCK
 
3965
  DialoG        ids;
 
3966
} GenomeprojidUserDialog, PNTR GenomeprojidUserDialogPtr;
 
3967
 
 
3968
typedef struct genomeprojiduserform {
 
3969
  FEATURE_FORM_BLOCK
 
3970
  SeqEntryPtr   sep;
 
3971
} GenomeprojidUserForm, PNTR GenomeprojidUserFormPtr;
 
3972
 
 
3973
static void UserObjectPtrToGenomeprojidDialog (DialoG d, Pointer data)
 
3974
 
 
3975
{
 
3976
  Char                       buf [64];
 
3977
  UserFieldPtr               curr;
 
3978
  ValNodePtr                 head = NULL;
 
3979
  ObjectIdPtr                oip;
 
3980
  Int4                       parentID;
 
3981
  Int4                       projectID;
 
3982
  GenomeprojidUserDialogPtr  rdp;
 
3983
  UserObjectPtr              uop;
 
3984
  Int4                       val;
 
3985
 
 
3986
  rdp = (GenomeprojidUserDialogPtr) GetObjectExtra (d);
 
3987
  if (rdp == NULL) return;
 
3988
  uop = (UserObjectPtr) data;
 
3989
  if (uop == NULL || uop->type == NULL || StringICmp (uop->type->str, "GenomeProjectsDB") != 0) {
 
3990
    PointerToDialog (rdp->ids, NULL);
 
3991
    return;
 
3992
  }
 
3993
  projectID = 0;
 
3994
  parentID = 0;
 
3995
  for (curr = uop->data; curr != NULL; curr = curr->next) {
 
3996
    oip = curr->label;
 
3997
    if (oip == NULL) continue;
 
3998
    if (StringICmp (oip->str, "ProjectID") == 0) {
 
3999
      if (curr->choice == 2) {
 
4000
        val = (Int4) curr->data.intvalue;
 
4001
        if (projectID > 0) {
 
4002
          sprintf (buf, "%ld\t%ld", (long) projectID, (long) parentID);
 
4003
          ValNodeCopyStr (&head, 0, buf);
 
4004
          parentID = 0;
 
4005
        }
 
4006
        projectID = val;
 
4007
      }
 
4008
    } else if (StringICmp (oip->str, "ParentID") == 0) {
 
4009
      if (curr->choice == 2) {
 
4010
        val = (Int4) curr->data.intvalue;
 
4011
        parentID = val;
 
4012
      }
 
4013
    }
 
4014
  }
 
4015
  if (projectID > 0) {
 
4016
    sprintf (buf, "%ld\t%ld", (long) projectID, (long) parentID);
 
4017
    ValNodeCopyStr (&head, 0, buf);
 
4018
  }
 
4019
 
 
4020
  PointerToDialog (rdp->ids, (Pointer) head);
 
4021
  ValNodeFreeData (head);
 
4022
}
 
4023
 
 
4024
static Pointer GenomeprojidDialogToUserObjectPtr (DialoG d)
 
4025
 
 
4026
{
 
4027
  Char                       buf [64];
 
4028
  ValNodePtr                 head;
 
4029
  Int4                       parentID;
 
4030
  Int4                       projectID;
 
4031
  CharPtr                    ptr1;
 
4032
  CharPtr                    ptr2;
 
4033
  GenomeprojidUserDialogPtr  rdp;
 
4034
  CharPtr                    str;
 
4035
  UserObjectPtr              uop;
 
4036
  long int                   val;
 
4037
  ValNodePtr                 vnp;
 
4038
 
 
4039
  rdp = (GenomeprojidUserDialogPtr) GetObjectExtra (d);
 
4040
  if (rdp == NULL) return NULL;
 
4041
 
 
4042
  uop = CreateGenomeProjectsDBUserObject ();
 
4043
  if (uop == NULL) return NULL;
 
4044
 
 
4045
  head = (ValNodePtr) DialogToPointer (rdp->ids);
 
4046
  if (head == NULL) return NULL;
 
4047
 
 
4048
  for (vnp = head; vnp != NULL; vnp = vnp->next) {
 
4049
    projectID = 0;
 
4050
    parentID = 0;
 
4051
    str = (CharPtr) vnp->data.ptrvalue;
 
4052
    if (StringHasNoText (str)) continue;
 
4053
    StringNCpy_0 (buf, str, sizeof (buf));
 
4054
    ptr1 = StringChr (buf, '\t');
 
4055
    if (ptr1 != NULL) {
 
4056
      *ptr1 = '\0';
 
4057
      ptr1++;
 
4058
      ptr2 = StringChr (ptr1, '\n');
 
4059
      if (ptr2 == NULL) {
 
4060
        ptr2 = StringChr (ptr1, '\t');
 
4061
      }
 
4062
      if (ptr2 != NULL) {
 
4063
        *ptr2 = '\0';
 
4064
      }
 
4065
      if (sscanf (buf, "%ld", &val) == 1 && val > 0) {
 
4066
        projectID = (Int4) val;
 
4067
        if (sscanf (ptr1, "%ld", &val) == 1 && val > 0) {
 
4068
          parentID = (Int4) val;
 
4069
        }
 
4070
        AddIDsToGenomeProjectsDBUserObject (uop, projectID, parentID);
 
4071
      }
 
4072
    }
 
4073
  }
 
4074
 
 
4075
  ValNodeFreeData (head);
 
4076
 
 
4077
  return uop;
 
4078
}
 
4079
 
 
4080
static void ValNodePtrToGenomeprojidDialog (DialoG d, Pointer data)
 
4081
 
 
4082
{
 
4083
  ValNodePtr   head;
 
4084
  Int2         j;
 
4085
  ValNodePtr   list;
 
4086
  CharPtr      str;
 
4087
  TagListPtr   tlp;
 
4088
  ValNodePtr   vnp;
 
4089
 
 
4090
  tlp = (TagListPtr) GetObjectExtra (d);
 
4091
  list = (ValNodePtr) data;
 
4092
  if (tlp != NULL) {
 
4093
    head = NULL;
 
4094
    while (list != NULL) {
 
4095
      vnp = ValNodeNew (head);
 
4096
      if (head == NULL) {
 
4097
        head = vnp;
 
4098
      }
 
4099
      if (vnp != NULL) {
 
4100
        str = MemNew (StringLen ((CharPtr) list->data.ptrvalue) + 3);
 
4101
        if (str != NULL) {
 
4102
          StringCpy (str, (CharPtr) list->data.ptrvalue);
 
4103
          StringCat (str, "\n");
 
4104
        }
 
4105
        vnp->data.ptrvalue = str;
 
4106
      }
 
4107
      list = list->next;
 
4108
    }
 
4109
    SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
 
4110
    tlp->vnp = head;
 
4111
    SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
 
4112
    for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
 
4113
    }
 
4114
    tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
 
4115
    CorrectBarMax (tlp->bar, tlp->max);
 
4116
    CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
 
4117
  }
 
4118
}
 
4119
 
 
4120
static Pointer GenomeprojidDialogToValNodePtr (DialoG d)
 
4121
 
 
4122
{
 
4123
  Char         ch;
 
4124
  ValNodePtr   head;
 
4125
  Int2         j;
 
4126
  Int2         len;
 
4127
  ValNodePtr   list;
 
4128
  Boolean      okay;
 
4129
  CharPtr      str;
 
4130
  TagListPtr   tlp;
 
4131
  ValNodePtr   vnp;
 
4132
 
 
4133
  head = NULL;
 
4134
  tlp = (TagListPtr) GetObjectExtra (d);
 
4135
  if (tlp != NULL && tlp->vnp != NULL) {
 
4136
    list = NULL;
 
4137
    for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
 
4138
      str = (CharPtr) vnp->data.ptrvalue;
 
4139
      okay = FALSE;
 
4140
      len = StringLen (str);
 
4141
      for (j = 0; j < len; j++) {
 
4142
        ch = str [j];
 
4143
        if (ch != ' ' && ch != '\t' && ch != '\n') {
 
4144
          okay = TRUE;
 
4145
        }
 
4146
      }
 
4147
      if (okay) {
 
4148
        list = ValNodeNew (list);
 
4149
        if (head == NULL) {
 
4150
          head = list;
 
4151
        }
 
4152
        if (list != NULL) {
 
4153
          list->choice = 0;
 
4154
          list->data.ptrvalue = StringSave (str);
 
4155
        }
 
4156
      }
 
4157
    }
 
4158
  }
 
4159
  return (Pointer) head;
 
4160
}
 
4161
 
 
4162
Uint2 genproj_types [] = {
 
4163
  TAGLIST_TEXT, TAGLIST_TEXT
 
4164
};
 
4165
 
 
4166
Uint2 genproj_widths [] = {
 
4167
  10, 10, 0
 
4168
};
 
4169
 
 
4170
static DialoG CreateGenomeProjectsDBDialog (GrouP g)
 
4171
 
 
4172
{
 
4173
  GrouP                      p;
 
4174
  GenomeprojidUserDialogPtr  rdp;
 
4175
  GrouP                      x;
 
4176
  GrouP                      y;
 
4177
 
 
4178
  p = HiddenGroup (g, -1, 0, NULL);
 
4179
  SetGroupSpacing (p, 10, 10);
 
4180
 
 
4181
  rdp = (GenomeprojidUserDialogPtr) MemNew (sizeof (GenomeprojidUserDialog));
 
4182
  if (rdp == NULL) return NULL;
 
4183
 
 
4184
  SetObjectExtra (p, rdp, NULL);
 
4185
  rdp->dialog = (DialoG) p;
 
4186
  rdp->todialog = UserObjectPtrToGenomeprojidDialog;
 
4187
  rdp->fromdialog = GenomeprojidDialogToUserObjectPtr;
 
4188
 
 
4189
  x = HiddenGroup (p, 0, 2, NULL);
 
4190
  y = HiddenGroup (x, 3, 0, NULL);
 
4191
  StaticPrompt (y, "Project ID", 10 * stdCharWidth, 0, programFont, 'c');
 
4192
  StaticPrompt (y, "Parent ID", 10 * stdCharWidth, 0, programFont, 'c');
 
4193
 
 
4194
  rdp->ids = CreateTagListDialog (x, 3, 2, -1,
 
4195
                                  genproj_types, genproj_widths, NULL,
 
4196
                                  ValNodePtrToGenomeprojidDialog,
 
4197
                                  GenomeprojidDialogToValNodePtr);
 
4198
 
 
4199
  return (DialoG) p;
 
4200
}
 
4201
 
 
4202
static void GenomeProjectsDBUserFormMessage (ForM f, Int2 mssg)
 
4203
 
 
4204
{
 
4205
  GenomeprojidUserFormPtr  rfp;
 
4206
 
 
4207
  rfp = (GenomeprojidUserFormPtr) GetObjectExtra (f);
 
4208
  if (rfp != NULL) {
 
4209
    switch (mssg) {
 
4210
      case VIB_MSG_CLOSE :
 
4211
        Remove (f);
 
4212
        break;
 
4213
      case VIB_MSG_CUT :
 
4214
        StdCutTextProc (NULL);
 
4215
        break;
 
4216
      case VIB_MSG_COPY :
 
4217
        StdCopyTextProc (NULL);
 
4218
        break;
 
4219
      case VIB_MSG_PASTE :
 
4220
        StdPasteTextProc (NULL);
 
4221
        break;
 
4222
      case VIB_MSG_DELETE :
 
4223
        StdDeleteTextProc (NULL);
 
4224
        break;
 
4225
      default :
 
4226
        if (rfp->appmessage != NULL) {
 
4227
          rfp->appmessage (f, mssg);
 
4228
        }
 
4229
        break;
 
4230
    }
 
4231
  }
 
4232
}
 
4233
 
 
4234
static ForM CreateGenomeProjectsDBDescForm (Int2 left, Int2 top, Int2 width,
 
4235
                                           Int2 height, CharPtr title, ValNodePtr sdp,
 
4236
                                           SeqEntryPtr sep, FormActnFunc actproc)
 
4237
 
 
4238
{
 
4239
  ButtoN                   b;
 
4240
  GrouP                    c;
 
4241
  GrouP                    g;
 
4242
  GenomeprojidUserFormPtr  rfp;
 
4243
  StdEditorProcsPtr        sepp;
 
4244
  WindoW                   w;
 
4245
 
 
4246
  w = NULL;
 
4247
  rfp = (GenomeprojidUserFormPtr) MemNew (sizeof (GenomeprojidUserForm));
 
4248
  if (rfp != NULL) {
 
4249
    w = FixedWindow (left, top, width, height, title, StdCloseWindowProc);
 
4250
    SetObjectExtra (w, rfp, StdDescFormCleanupProc);
 
4251
    rfp->form = (ForM) w;
 
4252
    rfp->actproc = actproc;
 
4253
    rfp->formmessage = GenomeProjectsDBUserFormMessage;
 
4254
 
 
4255
    rfp->sep = sep;
 
4256
 
 
4257
#ifndef WIN_MAC
 
4258
    CreateStdEditorFormMenus (w);
 
4259
#endif
 
4260
    sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
 
4261
    if (sepp != NULL) {
 
4262
      SetActivate (w, sepp->activateForm);
 
4263
      rfp->appmessage = sepp->handleMessages;
 
4264
    }
 
4265
 
 
4266
    g = HiddenGroup (w, -1, 0, NULL);
 
4267
    rfp->data = CreateGenomeProjectsDBDialog (g);
 
4268
 
 
4269
    c = HiddenGroup (w, 2, 0, NULL);
 
4270
    b = DefaultButton (c, "Accept", StdAcceptFormButtonProc);
 
4271
    SetObjectExtra (b, rfp, NULL);
 
4272
    PushButton (c, "Cancel", StdCancelButtonProc);
 
4273
    AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
 
4274
    RealizeWindow (w);
 
4275
  }
 
4276
  return (ForM) w;
 
4277
}
 
4278
 
 
4279
extern Int2 LIBCALLBACK GenomeProjectsDBUserGenFunc (Pointer data);
 
4280
extern Int2 LIBCALLBACK GenomeProjectsDBUserGenFunc (Pointer data)
 
4281
 
 
4282
{
 
4283
  ObjectIdPtr              oip;
 
4284
  OMProcControlPtr         ompcp;
 
4285
  OMUserDataPtr            omudp;
 
4286
  ObjMgrProcPtr            proc;
 
4287
  GenomeprojidUserFormPtr  rfp;
 
4288
  ValNodePtr               sdp;
 
4289
  SeqEntryPtr              sep;
 
4290
  UserObjectPtr            uop;
 
4291
  WindoW                   w;
 
4292
 
 
4293
  ompcp = (OMProcControlPtr) data;
 
4294
  w = NULL;
 
4295
  sdp = NULL;
 
4296
  sep = NULL;
 
4297
  uop = NULL;
 
4298
  if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
 
4299
  proc = ompcp->proc;
 
4300
  switch (ompcp->input_itemtype) {
 
4301
    case OBJ_SEQDESC :
 
4302
      sdp = (ValNodePtr) ompcp->input_data;
 
4303
      if (sdp != NULL && sdp->choice != Seq_descr_user) {
 
4304
        return OM_MSG_RET_ERROR;
 
4305
      }
 
4306
      uop = (UserObjectPtr) sdp->data.ptrvalue;
 
4307
      break;
 
4308
    case OBJ_BIOSEQ :
 
4309
      break;
 
4310
    case OBJ_BIOSEQSET :
 
4311
      break;
 
4312
    case 0 :
 
4313
      break;
 
4314
    default :
 
4315
      return OM_MSG_RET_ERROR;
 
4316
  }
 
4317
  omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
 
4318
                                ompcp->input_itemtype, ompcp->proc->procid);
 
4319
  if (omudp != NULL) {
 
4320
    if (StringCmp (proc->procname, "Edit GenomeProjectsDB User Desc") == 0) {
 
4321
      rfp = (GenomeprojidUserFormPtr) omudp->userdata.ptrvalue;
 
4322
      if (rfp != NULL) {
 
4323
        Select (rfp->form);
 
4324
      }
 
4325
      return OM_MSG_RET_DONE;
 
4326
    } else {
 
4327
      return OM_MSG_RET_OK; /* not this type, check next registered user object editor */
 
4328
    }
 
4329
  }
 
4330
  if (uop != NULL) {
 
4331
    oip = uop->type;
 
4332
    if (oip == NULL || oip->str == NULL) return OM_MSG_RET_OK;
 
4333
    if (StringCmp (oip->str, "GenomeProjectsDB") != 0) return OM_MSG_RET_OK;
 
4334
  }
 
4335
  sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
 
4336
  w = (WindoW) CreateGenomeProjectsDBDescForm (-50, -33, -10, -10,
 
4337
                                               "Genome Projects DB", sdp, sep,
 
4338
                                               StdDescFormActnProc);
 
4339
  rfp = (GenomeprojidUserFormPtr) GetObjectExtra (w);
 
4340
  if (rfp != NULL) {
 
4341
    rfp->input_entityID = ompcp->input_entityID;
 
4342
    rfp->input_itemID = ompcp->input_itemID;
 
4343
    rfp->input_itemtype = ompcp->input_itemtype;
 
4344
    rfp->this_itemtype = OBJ_SEQDESC;
 
4345
    rfp->this_subtype = Seq_descr_user;
 
4346
    rfp->procid = ompcp->proc->procid;
 
4347
    rfp->proctype = ompcp->proc->proctype;
 
4348
    rfp->userkey = OMGetNextUserKey ();
 
4349
    omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
 
4350
                                   OMPROC_EDIT, rfp->userkey);
 
4351
    if (omudp != NULL) {
 
4352
      omudp->userdata.ptrvalue = (Pointer) rfp;
 
4353
      omudp->messagefunc = StdVibrantEditorMsgFunc;
 
4354
    }
 
4355
    SendMessageToForm (rfp->form, VIB_MSG_INIT);
 
4356
    if (sdp != NULL) {
 
4357
      PointerToDialog (rfp->data, (Pointer) sdp->data.ptrvalue);
 
4358
      SetClosestParentIfDuplicating ((BaseFormPtr) rfp);
 
4359
    }
 
4360
  }
 
4361
  Show (w);
 
4362
  Select (w);
 
4363
  return OM_MSG_RET_DONE;
 
4364
}
 
4365
 
 
4366
 
 
4367
 
3855
4368
extern Int2 LIBCALLBACK RefGeneUserGenFunc (Pointer data);
3856
4369
 
3857
4370
#define REFGENE_ASSEMBLY   1
7887
8400
  Update (); 
7888
8401
}
7889
8402
 
 
8403
 
 
8404
typedef struct convertgaptounknown
 
8405
{
 
8406
  FEATURE_FORM_BLOCK
 
8407
  
 
8408
  TexT start_unknown_txt;
 
8409
  Int4 start_unknown;
 
8410
} ConvertGapToUnknownData, PNTR ConvertGapToUnknownPtr;
 
8411
 
 
8412
 
 
8413
static void FixDeltaFeatures (BioseqPtr bsp, Int4 offset, Int4 len_diff)
 
8414
{
 
8415
  SeqFeatPtr             sfp;
 
8416
  SeqMgrFeatContext      fcontext;
 
8417
  
 
8418
  if (len_diff == 0)
 
8419
  {
 
8420
    return;
 
8421
  }
 
8422
  for (sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
 
8423
       sfp != NULL;
 
8424
       sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext))
 
8425
  {
 
8426
    AdjustFeatureForGapChange (sfp, bsp, offset, len_diff);
 
8427
  }  
 
8428
}
 
8429
 
 
8430
static void ConvertGapFeaturesToUnknownCallback (BioseqPtr bsp, Pointer userdata)
 
8431
{
 
8432
  ConvertGapToUnknownPtr cgtup;
 
8433
  DeltaSeqPtr            dsp;
 
8434
  SeqLitPtr              slip;
 
8435
  SeqLocPtr              slp;
 
8436
  Int4                   len_diff;
 
8437
  Int4                   offset = 0, add_len;
 
8438
  
 
8439
  if (bsp == NULL || bsp->repr != Seq_repr_delta 
 
8440
      || bsp->seq_ext_type != 4 || bsp->seq_ext == NULL
 
8441
      || userdata == NULL)
 
8442
  {
 
8443
    return;
 
8444
  }
 
8445
  
 
8446
  cgtup = (ConvertGapToUnknownPtr) userdata;
 
8447
  
 
8448
  dsp = (DeltaSeqPtr) bsp->seq_ext;
 
8449
  while (dsp != NULL)
 
8450
  {
 
8451
    add_len = 0;
 
8452
    if (dsp->choice == 1 && dsp->data.ptrvalue != NULL)
 
8453
    {
 
8454
      slp = (SeqLocPtr) dsp->data.ptrvalue;
 
8455
      add_len = SeqLocLen (slp);
 
8456
    }
 
8457
    else if (dsp->choice == 2 && dsp->data.ptrvalue != NULL)
 
8458
    {
 
8459
      slip = (SeqLitPtr) (dsp->data.ptrvalue);
 
8460
      add_len = slip->length;
 
8461
      if (slip->seq_data == NULL
 
8462
          && slip->length >= cgtup->start_unknown)
 
8463
      {
 
8464
        len_diff = slip->length - 100;
 
8465
        slip->length = 100;
 
8466
        if (slip->fuzz != NULL)
 
8467
        {
 
8468
          slip->fuzz = IntFuzzFree (slip->fuzz);
 
8469
        }
 
8470
        slip->fuzz = IntFuzzNew();
 
8471
        slip->fuzz->choice = 4;
 
8472
        
 
8473
        if (len_diff > 0) {
 
8474
            FixDeltaFeatures (bsp, offset, len_diff);
 
8475
        }
 
8476
        add_len -= len_diff;      
 
8477
      }
 
8478
    }
 
8479
    offset += add_len;
 
8480
    dsp = dsp->next;
 
8481
  }
 
8482
  bsp->length = offset;
 
8483
}
 
8484
 
 
8485
static void ConvertGapFeaturesToUnknownButton (ButtoN b)
 
8486
{
 
8487
  ConvertGapToUnknownPtr cgtup;
 
8488
  SeqEntryPtr            sep;
 
8489
  CharPtr                str;
 
8490
  
 
8491
  cgtup = (ConvertGapToUnknownPtr) GetObjectExtra (b);
 
8492
  if (cgtup == NULL)
 
8493
  {
 
8494
    return;
 
8495
  }
 
8496
  
 
8497
  str = SaveStringFromText (cgtup->start_unknown_txt);
 
8498
  if (StringHasNoText (str))
 
8499
  {
 
8500
    str = MemFree (str);
 
8501
    return;
 
8502
  }
 
8503
  
 
8504
  cgtup->start_unknown = atoi (str);
 
8505
  str = MemFree (str);
 
8506
  if (cgtup->start_unknown <= 0)
 
8507
  {
 
8508
    return;
 
8509
  }
 
8510
  
 
8511
  WatchCursor();
 
8512
  Update();
 
8513
  
 
8514
  sep = GetTopSeqEntryForEntityID (cgtup->input_entityID);
 
8515
  
 
8516
  VisitBioseqsInSep (sep, cgtup, ConvertGapFeaturesToUnknownCallback);
 
8517
  
 
8518
  ObjMgrSetDirtyFlag (cgtup->input_entityID, TRUE);
 
8519
  ObjMgrSendMsg (OM_MSG_UPDATE, cgtup->input_entityID, 0, 0);
 
8520
  Remove (cgtup->form);
 
8521
  ArrowCursor ();
 
8522
  Update (); 
 
8523
}
 
8524
 
 
8525
extern void ConvertGapFeaturesToUnknown (IteM i)
 
8526
{
 
8527
  BaseFormPtr            bfp;
 
8528
  ConvertGapToUnknownPtr cgtup;
 
8529
  WindoW                 w;
 
8530
  GrouP                  h, g, c;
 
8531
  ButtoN                 b;
 
8532
 
 
8533
#ifdef WIN_MAC
 
8534
  bfp = currentFormDataPtr;
 
8535
#else
 
8536
  bfp = GetObjectExtra (i);
 
8537
#endif
 
8538
  if (bfp == NULL) return;
 
8539
 
 
8540
  cgtup = (ConvertGapToUnknownPtr) MemNew (sizeof (ConvertGapToUnknownData));
 
8541
  if (cgtup == NULL) return;
 
8542
  w = FixedWindow (-50, -33, -10, -10, "Convert Known Length Gaps to Unknown", StdCloseWindowProc);
 
8543
  SetObjectExtra (w, cgtup, StdCleanupFormProc);
 
8544
  cgtup->form = (ForM) w;
 
8545
  cgtup->input_entityID = bfp->input_entityID;
 
8546
  
 
8547
  h = HiddenGroup (w, -1, 0, NULL);
 
8548
  SetGroupSpacing (h, 10, 10);
 
8549
  g = HiddenGroup (h, 2, 0, NULL);
 
8550
  StaticPrompt (g, "Convert gaps longer or equal to", 0, popupMenuHeight, programFont, 'r');
 
8551
  cgtup->start_unknown_txt = DialogText (g, "100", 10, NULL);
 
8552
  
 
8553
  c = HiddenGroup (h, 2, 0, NULL);
 
8554
  SetGroupSpacing (c, 10, 10);
 
8555
  b = PushButton (c, "Accept", ConvertGapFeaturesToUnknownButton);
 
8556
  SetObjectExtra (b, cgtup, NULL);
 
8557
  PushButton (c, "Cancel", StdCancelButtonProc);
 
8558
  
 
8559
  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
 
8560
  
 
8561
  Show (w);
 
8562
}
 
8563
 
 
8564
 
 
8565
typedef struct changegaplen
 
8566
{
 
8567
  FEATURE_FORM_BLOCK
 
8568
  
 
8569
  TexT   length_txt;
 
8570
  Int4   length;
 
8571
} ChangeGapLenData, PNTR ChangeGapLenPtr;
 
8572
 
 
8573
 
 
8574
static void ChangeOneGapLength (SeqFeatPtr sfp, Int4 new_length)
 
8575
{
 
8576
  BioseqPtr   bsp;
 
8577
  DeltaSeqPtr dsp;
 
8578
  SeqLitPtr              slip;
 
8579
  SeqLocPtr              slp;
 
8580
  Int4                   len_diff;
 
8581
  Int4                   offset = 0, gap_start;
 
8582
  
 
8583
  if (sfp == NULL || sfp->idx.subtype != FEATDEF_gap || new_length < 0
 
8584
      || new_length == SeqLocLen (sfp->location))
 
8585
  {
 
8586
    return;
 
8587
  }
 
8588
  
 
8589
  bsp = BioseqFindFromSeqLoc (sfp->location);
 
8590
  if (bsp == NULL || bsp->repr != Seq_repr_delta 
 
8591
      || bsp->seq_ext_type != 4 || bsp->seq_ext == NULL)
 
8592
  {
 
8593
    return;
 
8594
  }
 
8595
  
 
8596
  gap_start = SeqLocStart (sfp->location);
 
8597
  
 
8598
  dsp = (DeltaSeqPtr) bsp->seq_ext;
 
8599
  while (dsp != NULL && offset < gap_start)
 
8600
  {
 
8601
    if (dsp->choice == 1 && dsp->data.ptrvalue != NULL)
 
8602
    {
 
8603
      slp = (SeqLocPtr) dsp->data.ptrvalue;
 
8604
      offset += SeqLocLen (slp);
 
8605
    }
 
8606
    else if (dsp->choice == 2 && dsp->data.ptrvalue != NULL)
 
8607
    {
 
8608
      slip = (SeqLitPtr) (dsp->data.ptrvalue);
 
8609
      offset += slip->length;
 
8610
    }
 
8611
    dsp = dsp->next;
 
8612
  }
 
8613
  
 
8614
  if (offset == gap_start && dsp != NULL && dsp->choice == 2 && dsp->data.ptrvalue != NULL)
 
8615
  {
 
8616
    slip = (SeqLitPtr) (dsp->data.ptrvalue);
 
8617
    if (slip->seq_data == NULL && slip->fuzz == NULL)
 
8618
    {
 
8619
      len_diff = slip->length - new_length;
 
8620
      slip->length = new_length;
 
8621
      FixDeltaFeatures (bsp, offset, len_diff);
 
8622
    }
 
8623
  }
 
8624
  
 
8625
  
 
8626
  bsp->length -= len_diff;
 
8627
}
 
8628
 
 
8629
 
 
8630
static void ChangeGapLength (ButtoN b)
 
8631
{
 
8632
  ChangeGapLenPtr   cglp;
 
8633
  SelStructPtr      sel;
 
8634
  SeqFeatPtr        sfp;
 
8635
  SeqMgrFeatContext fcontext;
 
8636
  CharPtr           str;
 
8637
 
 
8638
  cglp = (ChangeGapLenPtr) GetObjectExtra (b);
 
8639
  if (cglp == NULL)
 
8640
  {
 
8641
    return;
 
8642
  }
 
8643
  
 
8644
  cglp->length = 0;
 
8645
  str = SaveStringFromText (cglp->length_txt);
 
8646
  if (!StringHasNoText (str))
 
8647
  {
 
8648
    cglp->length = atoi (str);
 
8649
  }
 
8650
  str = MemFree (str);
 
8651
  if (cglp->length < 1)
 
8652
  {
 
8653
    Message (MSG_ERROR, "Must select a gap size greater than zero!");
 
8654
    return;
 
8655
  }
 
8656
  
 
8657
  sel = ObjMgrGetSelected ();
 
8658
  if (sel == NULL)
 
8659
  {
 
8660
    Message (MSG_ERROR, "No gaps selected!");
 
8661
    return;
 
8662
  }
 
8663
  WatchCursor ();
 
8664
  Update ();
 
8665
  while (sel != NULL)
 
8666
  {
 
8667
    if (sel->entityID == cglp->input_entityID
 
8668
        && sel->itemtype == OBJ_SEQFEAT)
 
8669
    {
 
8670
      sfp = SeqMgrGetDesiredFeature (cglp->input_entityID, NULL, sel->itemID, 0, NULL, &fcontext);
 
8671
      if (sfp != NULL && sfp->idx.subtype == FEATDEF_gap)
 
8672
      {
 
8673
        ChangeOneGapLength (sfp, cglp->length);
 
8674
      }
 
8675
    }
 
8676
    sel = sel->next;
 
8677
  }
 
8678
  
 
8679
  ObjMgrSetDirtyFlag (cglp->input_entityID, TRUE);
 
8680
  ObjMgrSendMsg (OM_MSG_UPDATE, cglp->input_entityID, 0, 0);
 
8681
  ArrowCursor ();
 
8682
  Update (); 
 
8683
  
 
8684
  if (!GetStatus (cglp->leave_dlg_up))
 
8685
  {
 
8686
    Remove (cglp->form);
 
8687
  }
 
8688
}
 
8689
 
 
8690
extern void ChangeKnownGapLength (IteM i)
 
8691
{
 
8692
  BaseFormPtr     bfp;
 
8693
  ChangeGapLenPtr cglp;
 
8694
  WindoW          w;
 
8695
  GrouP           h, g, c;
 
8696
  ButtoN          b;
 
8697
 
 
8698
#ifdef WIN_MAC
 
8699
  bfp = currentFormDataPtr;
 
8700
#else
 
8701
  bfp = GetObjectExtra (i);
 
8702
#endif
 
8703
  if (bfp == NULL) return;
 
8704
 
 
8705
  cglp = (ChangeGapLenPtr) MemNew (sizeof (ChangeGapLenData));
 
8706
  if (cglp == NULL) return;
 
8707
  w = FixedWindow (-50, -33, -10, -10, "Change Length of Selected Known Length Gaps", StdCloseWindowProc);
 
8708
  SetObjectExtra (w, cglp, StdCleanupFormProc);
 
8709
  cglp->form = (ForM) w;
 
8710
  cglp->input_entityID = bfp->input_entityID;
 
8711
  
 
8712
  h = HiddenGroup (w, -1, 0, NULL);
 
8713
  SetGroupSpacing (h, 10, 10);
 
8714
  g = HiddenGroup (h, 2, 0, NULL);
 
8715
  StaticPrompt (g, "Change length to", 0, popupMenuHeight, programFont, 'r');
 
8716
  cglp->length_txt = DialogText (g, "100", 10, NULL);
 
8717
  
 
8718
  c = HiddenGroup (h, 3, 0, NULL);
 
8719
  SetGroupSpacing (c, 10, 10);
 
8720
  b = PushButton (c, "Accept", ChangeGapLength);
 
8721
  SetObjectExtra (b, cglp, NULL);
 
8722
  PushButton (c, "Cancel", StdCancelButtonProc);
 
8723
  cglp->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
 
8724
  
 
8725
  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
 
8726
  
 
8727
  Show (w);
 
8728
}
 
8729
 
7890
8730
extern void ConvertSelectedGapFeaturesToKnown (IteM i)
7891
8731
{
7892
8732
  ConvertSelectedGapFeatures (i, TRUE);  
7897
8737
  ConvertSelectedGapFeatures (i, FALSE);
7898
8738
}
7899
8739
 
7900
 
static void CombineAdjacentKnownGaps (BioseqPtr bsp, Pointer userdata)
 
8740
 
 
8741
static Int4 CountNsAtEndOfSeqLit (SeqLitPtr slip, Uint2 which_end)
 
8742
{
 
8743
  Int2         residue;
 
8744
  Int4         change_len = 0;
 
8745
  
 
8746
  if (slip == NULL || slip->seq_data == NULL)
 
8747
  {
 
8748
    return 0;
 
8749
  }
 
8750
  
 
8751
  if (slip->seq_data_type != Seq_code_iupacna)
 
8752
  {
 
8753
    slip->seq_data = BSConvertSeq(slip->seq_data, Seq_code_iupacna, 
 
8754
                          slip->seq_data_type, 
 
8755
                          slip->length);
 
8756
    slip->seq_data_type = Seq_code_iupacna;
 
8757
  }
 
8758
  
 
8759
  if (which_end == SEQLOC_LEFT_END)
 
8760
  {
 
8761
    BSSeek(slip->seq_data, 0, SEEK_SET);
 
8762
  }
 
8763
  else
 
8764
  {
 
8765
    BSSeek(slip->seq_data, slip->length - 1, SEEK_SET);    
 
8766
  }
 
8767
  
 
8768
  residue = BSGetByte(slip->seq_data);
 
8769
  while (change_len < slip->length && residue == 'N')
 
8770
  {
 
8771
    change_len++;
 
8772
    if (which_end != SEQLOC_LEFT_END)
 
8773
    {
 
8774
      BSSeek (slip->seq_data, slip->length - change_len - 1, SEEK_SET);
 
8775
    }
 
8776
    residue = BSGetByte (slip->seq_data);
 
8777
  }
 
8778
 
 
8779
  return change_len;
 
8780
}
 
8781
 
 
8782
static void RemoveSeqLitEnd (SeqLitPtr slip, Int4 change_len, Uint2 which_end)
 
8783
{
 
8784
  ByteStorePtr bs_new;
 
8785
 
 
8786
  if (slip == NULL || change_len < 1)
 
8787
  {
 
8788
    return;
 
8789
  }
 
8790
  if (slip->seq_data_type != Seq_code_iupacna)
 
8791
  {
 
8792
    slip->seq_data = BSConvertSeq(slip->seq_data, Seq_code_iupacna, 
 
8793
                                  slip->seq_data_type, 
 
8794
                                  slip->length);
 
8795
    slip->seq_data_type = Seq_code_iupacna;
 
8796
  }
 
8797
  bs_new = BSNew (slip->length - change_len);
 
8798
  if (which_end == SEQLOC_LEFT_END)
 
8799
  {
 
8800
    BSSeek (slip->seq_data, change_len, SEEK_SET);
 
8801
  }
 
8802
  else
 
8803
  {
 
8804
    BSSeek(slip->seq_data, 0, SEEK_SET);
 
8805
  }
 
8806
  BSInsertFromBS (bs_new, slip->seq_data, slip->length - change_len);
 
8807
  slip->seq_data = BSFree (slip->seq_data);
 
8808
  slip->seq_data = bs_new;
 
8809
  slip->length -= change_len;
 
8810
}
 
8811
 
 
8812
static void ExpandGapsToIncludeFlankingNs (BioseqPtr bsp, Pointer userdata)
 
8813
{
 
8814
  DeltaSeqPtr  dsp;
 
8815
  Int4         offset = 0, last_length = 0, change_len, add_offset;
 
8816
  SeqLocPtr    slp;
 
8817
  SeqLitPtr    slip, prev_slip = NULL, next_slip;
 
8818
  
 
8819
  if (bsp == NULL || bsp->repr != Seq_repr_delta 
 
8820
      || bsp->seq_ext_type != 4 || bsp->seq_ext == NULL)
 
8821
  {
 
8822
    return;
 
8823
  }
 
8824
  
 
8825
  for (dsp = bsp->seq_ext; dsp != NULL; dsp = dsp->next)
 
8826
  {
 
8827
    add_offset = 0;
 
8828
    if (dsp->choice == 1)
 
8829
    {
 
8830
      slp = (SeqLocPtr) dsp->data.ptrvalue;
 
8831
      add_offset = SeqLocLen (slp);
 
8832
      last_length = 0;
 
8833
      prev_slip = NULL;
 
8834
    }
 
8835
    else if (dsp->choice == 2)
 
8836
    {
 
8837
      slip = (SeqLitPtr) dsp->data.ptrvalue;
 
8838
      add_offset = slip->length;
 
8839
      if (slip->seq_data == NULL)
 
8840
      {
 
8841
        if (slip->fuzz == NULL)
 
8842
        {
 
8843
          /* check for Ns before gap of known length */
 
8844
          if (prev_slip != NULL && last_length > 0)
 
8845
          {
 
8846
            change_len = CountNsAtEndOfSeqLit (prev_slip, SEQLOC_RIGHT_END);
 
8847
 
 
8848
            if (change_len > 0)
 
8849
            {
 
8850
              RemoveSeqLitEnd (prev_slip, change_len, SEQLOC_RIGHT_END);
 
8851
              slip->length += change_len;
 
8852
            }
 
8853
          }
 
8854
          /* check for Ns after gap of known length */
 
8855
          if (dsp->next != NULL && dsp->next->choice == 2 && dsp->next->data.ptrvalue != NULL)
 
8856
          {
 
8857
            next_slip = (SeqLitPtr) dsp->next->data.ptrvalue;
 
8858
            change_len = CountNsAtEndOfSeqLit (next_slip, SEQLOC_LEFT_END);
 
8859
            
 
8860
            if (change_len > 0)
 
8861
            {
 
8862
              RemoveSeqLitEnd (next_slip, change_len, SEQLOC_LEFT_END);
 
8863
              slip->length += change_len;
 
8864
              add_offset += change_len;
 
8865
            }
 
8866
          }
 
8867
        }
 
8868
        prev_slip = NULL;
 
8869
        last_length = 0;
 
8870
      }
 
8871
      else
 
8872
      {
 
8873
        prev_slip = slip;
 
8874
        last_length = slip->length;
 
8875
      }
 
8876
    }
 
8877
    else
 
8878
    {
 
8879
      prev_slip = NULL;
 
8880
      last_length = 0;
 
8881
    }
 
8882
    offset += add_offset;
 
8883
  }
 
8884
  BioseqPack (bsp);
 
8885
}
 
8886
 
 
8887
extern void AddFlankingNsToKnownLengthGaps (IteM i)
 
8888
{
 
8889
  BaseFormPtr       bfp;
 
8890
  SeqEntryPtr       sep;
 
8891
 
 
8892
#ifdef WIN_MAC
 
8893
  bfp = currentFormDataPtr;
 
8894
#else
 
8895
  bfp = GetObjectExtra (i);
 
8896
#endif
 
8897
  if (bfp == NULL) return;
 
8898
 
 
8899
  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
 
8900
  
 
8901
  WatchCursor ();
 
8902
  Update ();
 
8903
  VisitBioseqsInSep (sep, NULL, ExpandGapsToIncludeFlankingNs);
 
8904
  
 
8905
  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
 
8906
  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
 
8907
  ArrowCursor ();
 
8908
  Update (); 
 
8909
}
 
8910
 
 
8911
 
 
8912
static void CombineAdjacentGapsCallback (BioseqPtr bsp, Pointer userdata)
7901
8913
{
7902
8914
  ValNodePtr vnp, prev_vnp = NULL, next_vnp;
7903
8915
  SeqLitPtr  litp, prev_litp = NULL;
 
8916
  SeqLocPtr  slp;
 
8917
  Int4       offset = 0;
 
8918
  Int4       len_diff;
 
8919
  SeqFeatPtr sfp;
 
8920
  SeqMgrFeatContext fcontext;
7904
8921
  
7905
8922
  if (bsp == NULL || bsp->repr != Seq_repr_delta)
7906
8923
  {
7916
8933
    {
7917
8934
      prev_vnp = NULL;
7918
8935
      prev_litp = NULL;
 
8936
      slp = (SeqLocPtr) vnp->data.ptrvalue;
 
8937
      offset += SeqLocLen (slp);
7919
8938
    }
7920
8939
    else if (vnp->choice == 2) 
7921
8940
    {
7922
8941
      litp = (SeqLitPtr) vnp->data.ptrvalue;
7923
 
      if (litp == NULL || litp->fuzz != NULL || litp->seq_data != NULL)
 
8942
      if (litp == NULL || litp->seq_data != NULL)
7924
8943
      {
7925
8944
        prev_vnp = NULL;
7926
8945
        prev_litp = NULL;
 
8946
        offset += litp->length;
7927
8947
      }
7928
8948
      else if (prev_vnp != NULL && prev_litp != NULL)
7929
8949
      {
7930
 
        /* combine two adjacent known-length gaps */
7931
 
        prev_litp->length += litp->length;
 
8950
        /* combine two adjacent gaps */
 
8951
        len_diff = 0;
 
8952
        offset = offset - prev_litp->length;
 
8953
        if (prev_litp->fuzz != NULL || litp->fuzz != NULL)
 
8954
        {
 
8955
          /* at least one is unknown length, so result will be unknown */
 
8956
          len_diff = prev_litp->length + litp->length - 100;
 
8957
          
 
8958
          prev_litp->length = 100;
 
8959
          if (prev_litp->fuzz == NULL)
 
8960
          {
 
8961
            prev_litp->fuzz = IntFuzzNew ();
 
8962
            prev_litp->fuzz->choice = 4;
 
8963
          }          
 
8964
        }
 
8965
        else
 
8966
        {
 
8967
          prev_litp->length += litp->length;
 
8968
        }
7932
8969
        prev_vnp->next = vnp->next;
7933
8970
        vnp->next = NULL;
7934
8971
        litp = SeqLitFree (litp);
7935
8972
        vnp = ValNodeFree (vnp);
 
8973
        if (len_diff != 0)
 
8974
        {
 
8975
          FixDeltaFeatures (bsp, offset, len_diff);
 
8976
        }
 
8977
        offset += prev_litp->length;
7936
8978
      }
7937
8979
      else
7938
8980
      {
7939
8981
        prev_vnp = vnp;
7940
8982
        prev_litp = litp;
 
8983
        offset += litp->length;
7941
8984
      }
7942
8985
    }
7943
 
  }  
 
8986
  }
 
8987
  bsp->length = offset;
 
8988
  for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, FEATDEF_CDS, &fcontext);
 
8989
       sfp != NULL;
 
8990
       sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, FEATDEF_CDS, &fcontext))
 
8991
  {
 
8992
    AdjustCDSLocationsForGapsCallback (sfp, NULL);
 
8993
  }
7944
8994
}
7945
8995
 
7946
 
extern void ConvertAdjacentKnownGapsToSingleGaps (IteM i)
 
8996
extern void CombineAdjacentGaps (IteM i)
7947
8997
{
7948
8998
  BaseFormPtr       bfp;
7949
8999
  SeqEntryPtr       sep;
7959
9009
  
7960
9010
  WatchCursor ();
7961
9011
  Update ();
7962
 
  VisitBioseqsInSep (sep, NULL, CombineAdjacentKnownGaps);
 
9012
  VisitBioseqsInSep (sep, NULL, CombineAdjacentGapsCallback);
7963
9013
  
7964
9014
  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
7965
9015
  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8010
9060
  
8011
9061
}
8012
9062
 
8013
 
static ProtRefPtr GetProtRefForCDSFeature (SeqFeatPtr sfp)
8014
 
{
8015
 
  SeqFeatXrefPtr    xref;           
8016
 
  ProtRefPtr        prp = NULL;
8017
 
  BioseqPtr         prot_bsp;
8018
 
  SeqFeatPtr        prot_sfp;
8019
 
  SeqMgrFeatContext context;
8020
 
  
8021
 
  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION)
8022
 
  {
8023
 
    return NULL;
8024
 
  }
8025
 
  
8026
 
  xref = sfp->xref;
8027
 
  while (xref != NULL 
8028
 
         && (xref->data.choice != SEQFEAT_PROT 
8029
 
             || xref->data.value.ptrvalue == NULL)) 
8030
 
  {
8031
 
    xref = xref->next;
8032
 
  }
8033
 
  if (xref != NULL)
8034
 
  {
8035
 
    prp = (ProtRefPtr) xref->data.value.ptrvalue;
8036
 
  }
8037
 
  else
8038
 
  {
8039
 
    prot_bsp = BioseqFindFromSeqLoc (sfp->product);
8040
 
    if (prot_bsp == NULL)
8041
 
    {
8042
 
      return NULL;
8043
 
    }
8044
 
  
8045
 
    prot_sfp = SeqMgrGetNextFeature (prot_bsp, NULL, SEQFEAT_PROT, FEATDEF_PROT, &context);
8046
 
    if (prot_sfp == NULL || prot_sfp->data.value.ptrvalue == NULL)
8047
 
    {
8048
 
      return NULL;
8049
 
    }
8050
 
  
8051
 
    prp = (ProtRefPtr) prot_sfp->data.value.ptrvalue;
8052
 
  }
8053
 
  return prp;
8054
 
}
8055
 
 
8056
 
static void GetPseudoProteinDescSample (SeqFeatPtr sfp, Pointer userdata)
8057
 
{
8058
 
  GetSamplePtr      gsp;
8059
 
  ProtRefPtr        prp = NULL;
8060
 
  Boolean           is_pseudo = FALSE;
8061
 
  GeneRefPtr        grp;
8062
 
  SeqFeatPtr        gene_sfp;
8063
 
  
8064
 
  if (sfp == NULL 
8065
 
      || sfp->data.choice != SEQFEAT_CDREGION 
8066
 
      || userdata == NULL)
8067
 
  {
8068
 
    return;
8069
 
  }
8070
 
  
8071
 
  /* check to see if this is a pseudo-CDS */
8072
 
  is_pseudo = sfp->pseudo;
8073
 
  if (!is_pseudo)
8074
 
  {
8075
 
    grp = SeqMgrGetGeneXref (sfp);
8076
 
    if (grp == NULL)
8077
 
    {
8078
 
      gene_sfp = SeqMgrGetOverlappingGene (sfp->location, NULL);
8079
 
      if (gene_sfp->pseudo)
8080
 
      {
8081
 
        is_pseudo = TRUE;
8082
 
      }
8083
 
      else 
8084
 
      {
8085
 
        grp = (GeneRefPtr) gene_sfp->data.value.ptrvalue;
8086
 
        if (grp != NULL && grp->pseudo)
8087
 
        {
8088
 
          is_pseudo = TRUE;
8089
 
        }
8090
 
      }
8091
 
    }
8092
 
    else if (grp->pseudo)
8093
 
    {
8094
 
      is_pseudo = TRUE;
8095
 
    }
8096
 
  }
8097
 
  if (!is_pseudo)
8098
 
  {
8099
 
    return;
8100
 
  }
8101
 
  
8102
 
  gsp = (GetSamplePtr) userdata;
8103
 
  
8104
 
  /* find ProtRefPtr with protein name and description */
8105
 
  prp = GetProtRefForCDSFeature (sfp);
8106
 
  if (prp == NULL)
8107
 
  {
8108
 
    return;
8109
 
  }
8110
 
  
8111
 
  if (prp->name != NULL && !StringHasNoText (prp->name->data.ptrvalue))
8112
 
  {
8113
 
    ValNodeAddPointer (&gsp->feat_dest_list, 1, sfp);
8114
 
    
8115
 
    if (!StringHasNoText (prp->desc))
8116
 
    {
8117
 
      if (StringHasNoText (gsp->sample_text))
8118
 
      {
8119
 
        gsp->sample_text = MemFree (gsp->sample_text);
8120
 
        gsp->sample_text = StringSave (prp->desc);
8121
 
      }
8122
 
      else if (StringCmp (gsp->sample_text, prp->desc) != 0)
8123
 
      {
8124
 
        gsp->all_same = FALSE;
8125
 
      }
8126
 
      gsp->num_found ++;  
8127
 
    }  
8128
 
  }
8129
 
}
8130
 
 
8131
 
extern void ConvertPseudoProteinNamesToProteinDescriptions (IteM i)
8132
 
{
8133
 
  BaseFormPtr       bfp;
8134
 
  SeqEntryPtr       sep;
8135
 
  GetSampleData     gsd;
8136
 
  ExistingTextPtr   etp = NULL;
8137
 
  ValNodePtr        vnp;
8138
 
  SeqFeatPtr        sfp;
8139
 
  ProtRefPtr        prp;
8140
 
 
8141
 
#ifdef WIN_MAC
8142
 
  bfp = currentFormDataPtr;
8143
 
#else
8144
 
  bfp = GetObjectExtra (i);
8145
 
#endif
8146
 
  if (bfp == NULL) return;
8147
 
 
8148
 
  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8149
 
  
8150
 
  WatchCursor ();
8151
 
  Update ();
8152
 
  
8153
 
  gsd.sample_text = NULL;
8154
 
  gsd.all_same = TRUE;
8155
 
  gsd.num_found = 0;
8156
 
  gsd.feat_dest_list = NULL;
8157
 
  VisitFeaturesInSep (sep, &gsd, GetPseudoProteinDescSample);
8158
 
  
8159
 
  etp = GetExistingTextHandlerInfo (&gsd, FALSE);
8160
 
  
8161
 
  for (vnp = gsd.feat_dest_list; vnp != NULL; vnp = vnp->next)
8162
 
  {
8163
 
    sfp = (SeqFeatPtr) vnp->data.ptrvalue;    
8164
 
    prp = GetProtRefForCDSFeature (sfp);
8165
 
    if (prp != NULL)
8166
 
    {
8167
 
      prp->desc = HandleExistingText (prp->desc, prp->name->data.ptrvalue, etp);
8168
 
      prp->name->data.ptrvalue = NULL;
8169
 
      prp->name = ValNodeFreeData (prp->name);
8170
 
    }
8171
 
  }
8172
 
  
8173
 
  gsd.feat_dest_list = ValNodeFree (gsd.feat_dest_list);
8174
 
  gsd.sample_text = MemFree (gsd.sample_text);
8175
 
  
8176
 
  etp = MemFree (etp);
8177
 
  
8178
 
  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
8179
 
  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8180
 
  ArrowCursor ();
8181
 
  Update (); 
8182
 
  
8183
 
}
8184
 
 
8185
9063
static void RemoveOneNomenclature (UserObjectPtr PNTR puop)
8186
9064
{
8187
9065
  UserObjectPtr  uop, obj, prev_obj, next_obj;
8407
9285
}
8408
9286
 
8409
9287
 
 
9288
/* Discrepancy Report */
 
9289
 
 
9290
typedef void (*DiscrepancyCallback) (ValNodePtr item_list, Pointer userdata);
 
9291
typedef void (*DiscrepancyCallbackDataFree) (Pointer userdata);
 
9292
 
 
9293
/* To add a new type of test, do ALL Of the following:
 
9294
 * 1. add an item to the DiscrepancyType enum (this will fill the disc_type value)
 
9295
 * 2. add a collection function and declare it with the others
 
9296
 * 3. add an item to discrepancy_info_list that corresponds with the position of the
 
9297
 *    new enum value.  If you are combining multiple types in one collection function,
 
9298
 *    be sure to list them together.
 
9299
 */
 
9300
 
 
9301
typedef enum {
 
9302
  DISC_GENE_MISSING = 0,
 
9303
  DISC_SUPERFLUOUS_GENE,
 
9304
  DISC_GENE_MISSING_LOCUS_TAG,
 
9305
  DISC_GENE_DUPLICATE_LOCUS_TAG,
 
9306
  DISC_GENE_LOCUS_TAG_BAD_FORMAT,
 
9307
  DISC_GENE_LOCUS_TAG_INCONSISTENT_PREFIX,
 
9308
  DISC_NON_GENE_LOCUS_TAG,
 
9309
  DISC_MISSING_PROTEIN_ID,
 
9310
  DISC_INCONSISTENT_PROTEIN_ID_PREFIX,
 
9311
  DISC_GENE_CDS_mRNA_LOCATION_CONFLICT,
 
9312
  DISC_GENE_PRODUCT_CONFLICT,
 
9313
  DISC_GENE_DUPLICATE_LOCUS,
 
9314
  DISC_EC_NUMBER_NOTE,
 
9315
  DISC_PSEUDO_MISMATCH,
 
9316
  DISC_JOINED_FEATURES,
 
9317
  DISC_OVERLAPPING_GENES,
 
9318
  DISC_OVERLAPPING_CDS,
 
9319
  DISC_SHORT_CONTIG,
 
9320
  DISC_INCONSISTENT_BIOSRC,
 
9321
  DISC_SUSPECT_PRODUCT_NAME,
 
9322
  DISC_INCONSISTENT_BIOSRC_DEFLINE,
 
9323
  MAX_DISC_TYPE
 
9324
} DiscrepancyType;
 
9325
 
 
9326
typedef void (*PerformDiscrepancyTest) PROTO ((SeqEntryPtr, ValNodePtr PNTR));
 
9327
 
 
9328
typedef struct discrepancyinfo 
 
9329
{
 
9330
  CharPtr                conf_name;
 
9331
  CharPtr                setting_name;
 
9332
  PerformDiscrepancyTest test_func;
 
9333
} DiscrepancyInfoData, PNTR DiscrepancyInfoPtr;
 
9334
 
 
9335
/* declarations for discrepancy tests */
 
9336
static void AddMissingAndSuperfluousGeneDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9337
static void AddDiscrepanciesForMissingOrNonUniqueGeneLocusTags (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9338
static void AddDiscrepanciesForNonGeneLocusTags (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9339
static void FindMissingProteinIDs (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9340
static void FindCDSmRNAGeneLocationDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9341
static void FindCDSGeneProductConflicts (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9342
static void FindDuplicateGeneLocus (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9343
static void AddECNumberNoteDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9344
static void FindPseudoDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9345
static void AddJoinedFeatureDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9346
static void AddOverlappingGeneDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9347
static void AddOverlappingCodingRegionDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9348
static void FindShortContigs (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9349
static void FindNonmatchingContigSources (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9350
static void FindSuspectProductNames (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9351
static void FindInconsistentSourceAndDefline (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list);
 
9352
 
 
9353
const DiscrepancyInfoData discrepancy_info_list[] = 
 
9354
{
 
9355
  { "Missing Genes", "MISSING_GENES", AddMissingAndSuperfluousGeneDiscrepancies },
 
9356
  { "Extra Genes", "EXTRA_GENES", AddDiscrepanciesForMissingOrNonUniqueGeneLocusTags },
 
9357
  { "Missing Locus Tags", "MISSING_LOCUS_TAGS", AddDiscrepanciesForMissingOrNonUniqueGeneLocusTags },
 
9358
  { "Duplicate Locus Tags", "DUPLICATE_LOCUS_TAGS", AddDiscrepanciesForMissingOrNonUniqueGeneLocusTags },
 
9359
  { "Bad Locus Tag Format", "BAD_LOCUS_TAG_FORMAT", AddDiscrepanciesForMissingOrNonUniqueGeneLocusTags },
 
9360
  { "Inconsistent Locus Tag Prefix", "INCONSISTENT_LOCUS_TAG_PREFIX", AddDiscrepanciesForMissingOrNonUniqueGeneLocusTags },
 
9361
  { "Nongene Locus Tag", "NON_GENE_LOCUS_TAG", AddDiscrepanciesForNonGeneLocusTags },
 
9362
  { "Missing Protein ID", "MISSING_PROTEIN_ID", FindMissingProteinIDs },
 
9363
  { "Inconsistent Protein ID", "INCONSISTENT_PROTEIN_ID", FindMissingProteinIDs },
 
9364
  { "Feature Location Conflict", "FEATURE_LOCATION_CONFLICT", FindCDSmRNAGeneLocationDiscrepancies },
 
9365
  { "Gene Product Conflict", "GENE_PRODUCT_CONFLICT", FindCDSGeneProductConflicts },
 
9366
  { "Duplicate Gene Locus", "DUPLICATE_GENE_LOCUS", FindDuplicateGeneLocus },
 
9367
  { "EC Number Note", "EC_NUMBER_NOTE", AddECNumberNoteDiscrepancies },
 
9368
  { "Pseudo Mismatch", "PSEUDO_MISMATCH", FindPseudoDiscrepancies },
 
9369
  { "Joined Features", "JOINED_FEATURES", AddJoinedFeatureDiscrepancies },
 
9370
  { "Overlapping Genes", "OVERLAPPING_GENES", AddOverlappingGeneDiscrepancies },
 
9371
  { "Overlapping CDS", "OVERLAPPING_CDS", AddOverlappingCodingRegionDiscrepancies },
 
9372
  { "Short Contig", "SHORT_CONTIG", FindShortContigs },
 
9373
  { "Inconsistent BioSource", "INCONSISTENT_BIOSOURCE", FindNonmatchingContigSources },
 
9374
  { "Suspect Product Name", "SUSPECT_PRODUCT_NAMES", FindSuspectProductNames },
 
9375
  { "Inconsistent Source And Definition Line", "INCONSISTENT_SOURCE_DEFLINE", FindInconsistentSourceAndDefline }
 
9376
    
 
9377
};
 
9378
 
 
9379
 
 
9380
typedef struct discrepancyitem 
 
9381
{
 
9382
  DiscrepancyType             disc_type;
 
9383
  CharPtr                     description;
 
9384
  ValNodePtr                  item_list;
 
9385
  DiscrepancyCallback         callback_func; 
 
9386
  DiscrepancyCallbackDataFree datafree_func; 
 
9387
  Pointer                     callback_data;
 
9388
  Boolean                     chosen;
 
9389
  ValNodePtr                  subcategories;
 
9390
  Boolean                     expanded;
 
9391
  Int4                        level;
 
9392
} DiscrepancyItemData, PNTR DiscrepancyItemPtr;
 
9393
 
 
9394
typedef struct discrepancyconfig
 
9395
{
 
9396
  Boolean conf_list[MAX_DISC_TYPE];
 
9397
  Boolean use_feature_table_format;
 
9398
} DiscrepancyConfigData, PNTR DiscrepancyConfigPtr;
 
9399
 
 
9400
typedef struct discrepancyreportform 
 
9401
{
 
9402
  FORM_MESSAGE_BLOCK
 
9403
  SeqEntryPtr     sep;
 
9404
  ValNodePtr      discrepancy_list;
 
9405
  DoC             doc;
 
9406
  DoC             item_list;
 
9407
  ButtoN          recheck_btn;
 
9408
  Int2            selected;
 
9409
  Int2            item_selected;
 
9410
  Int2            clicked;
 
9411
  Boolean         dblClick;
 
9412
  BaseFormPtr     bfp;
 
9413
  
 
9414
  Int4            num_levels;
 
9415
  Nlm_ColPtr PNTR col_fmt_array_array;
 
9416
  DiscrepancyConfigPtr dcp;
 
9417
} DiscrepancyReportFormData, PNTR DiscrepancyReportFormPtr;
 
9418
 
 
9419
 
 
9420
static DiscrepancyConfigPtr DiscrepancyConfigFree (DiscrepancyConfigPtr dcp)
 
9421
{
 
9422
  return MemFree (dcp);  
 
9423
}
 
9424
 
 
9425
static DiscrepancyConfigPtr DiscrepancyConfigNew (void)
 
9426
{
 
9427
  DiscrepancyConfigPtr dcp;
 
9428
  Int4                 i;
 
9429
  
 
9430
  dcp = (DiscrepancyConfigPtr) MemNew (sizeof (DiscrepancyConfigData));
 
9431
  for (i = 0; i < MAX_DISC_TYPE; i++)
 
9432
  {
 
9433
    dcp->conf_list[i] = TRUE;
 
9434
  }
 
9435
  dcp->use_feature_table_format = FALSE;
 
9436
  return dcp;
 
9437
}
 
9438
 
 
9439
static DiscrepancyConfigPtr ReadDiscrepancyConfig (void)
 
9440
{
 
9441
  DiscrepancyConfigPtr dcp;
 
9442
  Int4                 i;
 
9443
  Char                 str[20];
 
9444
  
 
9445
  dcp = DiscrepancyConfigNew();
 
9446
  if (dcp != NULL)
 
9447
  {
 
9448
    for (i = 0; i < MAX_DISC_TYPE; i++)
 
9449
    {
 
9450
      if (GetSequinAppParam ("DISCREPANCY_REPORT", discrepancy_info_list[i].setting_name, NULL, str, sizeof (str))) {
 
9451
        if (StringICmp (str, "FALSE") == 0) {
 
9452
          dcp->conf_list[i] = FALSE;
 
9453
        }
 
9454
      }
 
9455
    }
 
9456
    if (GetSequinAppParam ("DISCREPANCY_REPORT", "USE_FEATURE_TABLE_FORMAT", NULL, str, sizeof (str))) {
 
9457
      if (StringICmp (str, "TRUE") == 0) {
 
9458
        dcp->use_feature_table_format = TRUE;
 
9459
      }
 
9460
    }
 
9461
  }
 
9462
  return dcp;
 
9463
}
 
9464
 
 
9465
static void SaveDiscrepancyConfig (DiscrepancyConfigPtr dcp)
 
9466
{
 
9467
  Int4 i;
 
9468
  
 
9469
  if (dcp == NULL)
 
9470
  {
 
9471
    return;
 
9472
  }
 
9473
  
 
9474
  for (i = 0; i < MAX_DISC_TYPE; i++)
 
9475
  {
 
9476
    if (dcp->conf_list[i])
 
9477
    {
 
9478
      SetAppParam ("SEQUINCUSTOM", "DISCREPANCY_REPORT", discrepancy_info_list[i].setting_name, "TRUE");
 
9479
    }
 
9480
    else
 
9481
    {
 
9482
      SetAppParam ("SEQUINCUSTOM", "DISCREPANCY_REPORT", discrepancy_info_list[i].setting_name, "FALSE");
 
9483
    }
 
9484
  }
 
9485
  if (dcp->use_feature_table_format)
 
9486
  {
 
9487
    SetAppParam ("SEQUINCUSTOM", "DISCREPANCY_REPORT", "USE_FEATURE_TABLE_FORMAT", "TRUE");
 
9488
  }
 
9489
  else
 
9490
  {
 
9491
    SetAppParam ("SEQUINCUSTOM", "DISCREPANCY_REPORT", "USE_FEATURE_TABLE_FORMAT", "FALSE");
 
9492
  }
 
9493
}
 
9494
 
 
9495
 
 
9496
static void UnselectDiscrepancyList(ButtoN b)
 
9497
{
 
9498
  ButtoN *test_options;
 
9499
  Int4    i;
 
9500
  
 
9501
  test_options = (ButtoN *) GetObjectExtra (b);
 
9502
  if (test_options != NULL)
 
9503
  {
 
9504
    for (i = 0; i < MAX_DISC_TYPE; i++)
 
9505
    {
 
9506
      SetStatus (test_options[i], FALSE);
 
9507
    }
 
9508
  }
 
9509
}
 
9510
 
 
9511
static void SelectDiscrepancyList(ButtoN b)
 
9512
{
 
9513
  ButtoN *test_options;
 
9514
  Int4    i;
 
9515
  
 
9516
  test_options = (ButtoN *) GetObjectExtra (b);
 
9517
  if (test_options != NULL)
 
9518
  {
 
9519
    for (i = 0; i < MAX_DISC_TYPE; i++)
 
9520
    {
 
9521
      SetStatus (test_options[i], TRUE);
 
9522
    }
 
9523
  }
 
9524
}
 
9525
 
 
9526
/* This function returns TRUE if there was a change to the discrepancy config,
 
9527
 * FALSE otherwise.
 
9528
 */
 
9529
static Boolean EditDiscrepancyConfig (DiscrepancyConfigPtr dcp)
 
9530
{
 
9531
  WindoW                w;
 
9532
  GrouP                 h, g, k, c;
 
9533
  ButtoN                b, use_feature_table_format_btn;
 
9534
  ModalAcceptCancelData acd;
 
9535
  Int4                  i;
 
9536
  ButtoN                test_options[MAX_DISC_TYPE];
 
9537
  Boolean               rval = FALSE;
 
9538
  
 
9539
  if (dcp == NULL)
 
9540
  {
 
9541
    return rval;
 
9542
  }
 
9543
  
 
9544
  acd.accepted = FALSE;
 
9545
  acd.cancelled = FALSE;
 
9546
  
 
9547
  w = ModalWindow(-20, -13, -10, -10, NULL);
 
9548
  h = HiddenGroup (w, -1, 0, NULL);
 
9549
  SetGroupSpacing (h, 10, 10);
 
9550
  
 
9551
  g = NormalGroup (h, 0, 10, "Discrepancy Tests to Run", programFont, NULL);
 
9552
  SetGroupSpacing (g, 10, 10);
 
9553
  for (i = 0; i < MAX_DISC_TYPE; i++)
 
9554
  {
 
9555
    test_options[i] = CheckBox (g, discrepancy_info_list[i].conf_name, NULL);
 
9556
    SetStatus (test_options[i], dcp->conf_list[i]);
 
9557
  }
 
9558
  
 
9559
  use_feature_table_format_btn = CheckBox (h, "Use feature table format for features in report", NULL);
 
9560
  SetStatus (use_feature_table_format_btn, dcp->use_feature_table_format);
 
9561
  
 
9562
  k = HiddenGroup (h, 2, 0, NULL);
 
9563
  b = PushButton (k, "Select All", SelectDiscrepancyList);
 
9564
  SetObjectExtra (b, test_options, NULL);
 
9565
  b = PushButton (k, "Unselect All", UnselectDiscrepancyList);
 
9566
  SetObjectExtra (b, test_options, NULL);  
 
9567
  
 
9568
  c = HiddenGroup (h, 3, 0, NULL);
 
9569
  b = PushButton (c, "Accept", ModalAcceptButton);
 
9570
  SetObjectExtra (b, &acd, NULL);
 
9571
  b = PushButton (c, "Cancel", ModalCancelButton);
 
9572
  SetObjectExtra (b, &acd, NULL);
 
9573
  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) use_feature_table_format_btn, (HANDLE) k, (HANDLE) c, NULL);
 
9574
  
 
9575
  Show(w); 
 
9576
  Select (w);
 
9577
  while (!acd.accepted && ! acd.cancelled)
 
9578
  {
 
9579
    ProcessExternalEvent ();
 
9580
    Update ();
 
9581
  }
 
9582
  ProcessAnEvent ();
 
9583
  if (acd.accepted)
 
9584
  {
 
9585
    for (i = 0; i < MAX_DISC_TYPE; i++)
 
9586
    {
 
9587
      dcp->conf_list [i] = GetStatus (test_options[i]);
 
9588
    }
 
9589
    dcp->use_feature_table_format = GetStatus (use_feature_table_format_btn);
 
9590
    rval = TRUE;
 
9591
    SaveDiscrepancyConfig (dcp);
 
9592
  }
 
9593
 
 
9594
  Remove (w);
 
9595
  return rval;
 
9596
}
 
9597
 
 
9598
 
 
9599
static WindoW discrepancyReportWindow = NULL;
 
9600
 
 
9601
 
 
9602
static ValNodePtr FreeDiscrepancyList (ValNodePtr list)
 
9603
{
 
9604
  DiscrepancyItemPtr dip;
 
9605
  
 
9606
  if (list == NULL)
 
9607
  {
 
9608
    return list;
 
9609
  }
 
9610
  FreeDiscrepancyList (list->next);
 
9611
  list->next = NULL;
 
9612
  dip = (DiscrepancyItemPtr) list->data.ptrvalue;
 
9613
  if (dip != NULL)
 
9614
  {
 
9615
    dip->description = MemFree (dip->description);
 
9616
    if (dip->datafree_func != NULL)
 
9617
    {
 
9618
      (dip->datafree_func) (dip->callback_data);
 
9619
    }
 
9620
    dip->item_list = ValNodeFree (dip->item_list);
 
9621
    
 
9622
    dip->subcategories = FreeDiscrepancyList (dip->subcategories);
 
9623
    dip = MemFree (dip);
 
9624
    list->data.ptrvalue = NULL;
 
9625
  }
 
9626
  list = ValNodeFree (list);
 
9627
  return list;
 
9628
}
 
9629
 
 
9630
 
 
9631
static DiscrepancyItemPtr 
 
9632
NewDiscrepancyItem 
 
9633
(DiscrepancyType disc_type,
 
9634
 CharPtr         description_fmt,
 
9635
 ValNodePtr      item_list)
 
9636
{
 
9637
  DiscrepancyItemPtr dip;
 
9638
  
 
9639
  dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
9640
  if (dip != NULL)
 
9641
  {
 
9642
    dip->disc_type = disc_type;
 
9643
    dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (description_fmt) + 15));
 
9644
    sprintf (dip->description, description_fmt, ValNodeLen (item_list));
 
9645
    dip->callback_func = NULL;
 
9646
    dip->datafree_func = NULL;
 
9647
    dip->callback_data = NULL;
 
9648
    dip->item_list = item_list;
 
9649
    dip->subcategories = NULL;
 
9650
    dip->expanded = FALSE;
 
9651
    dip->level = 0;
 
9652
  }
 
9653
  return dip;  
 
9654
}
 
9655
 
 
9656
 
 
9657
static void 
 
9658
RemoveUnwantedDiscrepancyItems 
 
9659
(ValNodePtr PNTR      discrepancy_list,
 
9660
 DiscrepancyConfigPtr dcp)
 
9661
{
 
9662
  ValNodePtr         vnp, prev = NULL, vnp_next;
 
9663
  DiscrepancyItemPtr dip;
 
9664
  
 
9665
  if (dcp == NULL || discrepancy_list == NULL || *discrepancy_list == NULL)
 
9666
  {
 
9667
    return;
 
9668
  }
 
9669
  
 
9670
  for (vnp = *discrepancy_list; vnp != NULL; vnp = vnp_next)
 
9671
  {
 
9672
    vnp_next = vnp->next;
 
9673
    dip = (DiscrepancyItemPtr) vnp->data.ptrvalue;
 
9674
    if (dip == NULL || ! dcp->conf_list[dip->disc_type])
 
9675
    {
 
9676
      if (prev == NULL)
 
9677
      {
 
9678
        *discrepancy_list = vnp_next;
 
9679
      }
 
9680
      else
 
9681
      {
 
9682
        prev->next = vnp_next;
 
9683
      }
 
9684
      vnp->next = NULL;
 
9685
      vnp = FreeDiscrepancyList (vnp);
 
9686
    }
 
9687
    else
 
9688
    {
 
9689
      prev = vnp;
 
9690
    }
 
9691
  }
 
9692
  
 
9693
}
 
9694
 
 
9695
 
 
9696
static void ValNodeLinkCopy (ValNodePtr PNTR list1, ValNodePtr list2)
 
9697
{
 
9698
  if (list1 == NULL) return;
 
9699
  while (list2 != NULL)
 
9700
  {
 
9701
    ValNodeAddPointer (list1, list2->choice, list2->data.ptrvalue);
 
9702
    list2 = list2->next;
 
9703
  }
 
9704
}
 
9705
 
 
9706
 
 
9707
static Boolean ValNodeStringListMatch (ValNodePtr vnp1, ValNodePtr vnp2)
 
9708
{
 
9709
  if (vnp1 == NULL && vnp2 == NULL)
 
9710
  {
 
9711
    return TRUE;
 
9712
  }
 
9713
  else if (vnp1 == NULL || vnp2 == NULL)
 
9714
  {
 
9715
    return FALSE;
 
9716
  }
 
9717
  else if (StringCmp (vnp1->data.ptrvalue, vnp2->data.ptrvalue) != 0)
 
9718
  {
 
9719
    return FALSE;
 
9720
  }
 
9721
  else
 
9722
  {
 
9723
    return ValNodeStringListMatch (vnp1->next, vnp2->next);
 
9724
  }
 
9725
}
 
9726
 
 
9727
 
 
9728
static Boolean GeneRefMatch (GeneRefPtr grp1, GeneRefPtr grp2)
 
9729
{
 
9730
  if (grp1 == NULL && grp2 == NULL)
 
9731
  {
 
9732
    return TRUE;
 
9733
  }
 
9734
  else if (grp1 == NULL || grp2 == NULL)
 
9735
  {
 
9736
    return FALSE;
 
9737
  }
 
9738
  else if (StringCmp (grp1->locus, grp2->locus) != 0
 
9739
           || StringCmp (grp1->allele, grp2->allele) != 0
 
9740
           || StringCmp (grp1->desc, grp2->desc) != 0
 
9741
           || StringCmp (grp1->maploc, grp2->maploc) != 0
 
9742
           || StringCmp (grp1->locus_tag, grp2->locus_tag) != 0
 
9743
           || (grp1->pseudo && !grp2->pseudo)
 
9744
           || (!grp1->pseudo && grp2->pseudo)
 
9745
           || !ValNodeStringListMatch (grp1->db, grp2->db)
 
9746
           || !ValNodeStringListMatch (grp1->syn, grp2->syn))
 
9747
  {
 
9748
    return FALSE;
 
9749
  }
 
9750
  else
 
9751
  {
 
9752
    return TRUE;
 
9753
  }
 
9754
}
 
9755
 
 
9756
 
 
9757
static void ExtractGeneFromListByGeneRef (ValNodePtr PNTR list, GeneRefPtr grp)
 
9758
{
 
9759
  ValNodePtr prev = NULL, this_vnp, next_vnp;
 
9760
  
 
9761
  if (list == NULL || grp == NULL)
 
9762
  {
 
9763
    return;
 
9764
  }
 
9765
  
 
9766
  this_vnp = *list;
 
9767
  while (this_vnp != NULL)
 
9768
  {
 
9769
    next_vnp = this_vnp->next;
 
9770
    if (GeneRefMatch (this_vnp->data.ptrvalue, grp))
 
9771
    {
 
9772
      if (prev == NULL)
 
9773
      {
 
9774
        *list = next_vnp;
 
9775
      }
 
9776
      else
 
9777
      {
 
9778
        prev->next = next_vnp;
 
9779
      }
 
9780
      this_vnp->next = NULL;
 
9781
      ValNodeFree (this_vnp);
 
9782
    }
 
9783
    else
 
9784
    {
 
9785
      prev = this_vnp;
 
9786
    }
 
9787
    this_vnp = next_vnp;    
 
9788
  }
 
9789
}
 
9790
 
 
9791
 
 
9792
static void ExtractGeneFromListByGene (ValNodePtr PNTR list, SeqFeatPtr gene)
 
9793
{
 
9794
  ValNodePtr prev = NULL, this_vnp, next_vnp;
 
9795
  
 
9796
  if (list == NULL || gene == NULL)
 
9797
  {
 
9798
    return;
 
9799
  }
 
9800
  
 
9801
  this_vnp = *list;
 
9802
  while (this_vnp != NULL)
 
9803
  {
 
9804
    next_vnp = this_vnp->next;
 
9805
    if (this_vnp->data.ptrvalue == gene)
 
9806
    {
 
9807
      if (prev == NULL)
 
9808
      {
 
9809
        *list = next_vnp;
 
9810
      }
 
9811
      else
 
9812
      {
 
9813
        prev->next = next_vnp;
 
9814
      }
 
9815
      this_vnp->next = NULL;
 
9816
      ValNodeFree (this_vnp);
 
9817
    }
 
9818
    else
 
9819
    {
 
9820
      prev = this_vnp;
 
9821
    }
 
9822
    this_vnp = next_vnp;    
 
9823
  }
 
9824
}
 
9825
 
 
9826
 
 
9827
static void 
 
9828
CheckGenesForFeatureType 
 
9829
(ValNodePtr PNTR features_without_genes,
 
9830
 ValNodePtr PNTR superfluous_genes,
 
9831
 BioseqPtr  bsp,
 
9832
 Uint2      feature_type,
 
9833
 Uint2      feature_subtype,
 
9834
 Boolean    makes_gene_not_superfluous)
 
9835
{
 
9836
  SeqFeatPtr         sfp, gene_sfp;
 
9837
  GeneRefPtr         grp;
 
9838
  SeqMgrFeatContext  context;
 
9839
  
 
9840
  if (features_without_genes == NULL
 
9841
      || superfluous_genes == NULL
 
9842
      || bsp == NULL)
 
9843
  {
 
9844
    return;
 
9845
  }
 
9846
  
 
9847
  for (sfp = SeqMgrGetNextFeature (bsp, NULL, feature_type, feature_subtype, &context);
 
9848
       sfp != NULL;
 
9849
       sfp = SeqMgrGetNextFeature (bsp, sfp, feature_type, feature_subtype, &context))
 
9850
  {
 
9851
    /* check for gene xref */
 
9852
    grp = SeqMgrGetGeneXref (sfp);
 
9853
    if (grp != NULL)
 
9854
    {
 
9855
      if (SeqMgrGeneIsSuppressed (grp))
 
9856
      {
 
9857
        ValNodeAddPointer (features_without_genes, OBJ_SEQFEAT, sfp);
 
9858
      }
 
9859
      else
 
9860
      {
 
9861
        ExtractGeneFromListByGeneRef (superfluous_genes, grp);
 
9862
      }
 
9863
    }
 
9864
    else
 
9865
    {
 
9866
      gene_sfp = SeqMgrGetOverlappingGene (sfp->location, NULL);
 
9867
      if (gene_sfp == NULL)
 
9868
      {
 
9869
        ValNodeAddPointer (features_without_genes, OBJ_SEQFEAT, sfp);
 
9870
      }
 
9871
      else if (makes_gene_not_superfluous)
 
9872
      {
 
9873
        ExtractGeneFromListByGene (superfluous_genes, gene_sfp);
 
9874
      }
 
9875
    }  
 
9876
  }  
 
9877
}
 
9878
 
 
9879
typedef struct misssupergenes
 
9880
{
 
9881
  ValNodePtr missing_list;
 
9882
  ValNodePtr super_list;
 
9883
} MissSuperGenesData, PNTR MissSuperGenesPtr;
 
9884
 
 
9885
 
 
9886
static void FindMissingGenes (BioseqPtr bsp, Pointer userdata)
 
9887
{
 
9888
  SeqFeatPtr         sfp;
 
9889
  SeqMgrFeatContext  context;
 
9890
  ValNodePtr         features_without_genes = NULL;
 
9891
  ValNodePtr         superfluous_genes = NULL;
 
9892
  MissSuperGenesPtr  msgp;
 
9893
  
 
9894
  if (bsp == NULL || userdata == NULL)
 
9895
  {
 
9896
    return;
 
9897
  }
 
9898
  
 
9899
  msgp = (MissSuperGenesPtr) userdata;
 
9900
  
 
9901
  for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_GENE, FEATDEF_GENE, &context);
 
9902
       sfp != NULL;
 
9903
       sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_GENE, FEATDEF_GENE, &context))
 
9904
  {
 
9905
    ValNodeAddPointer (&superfluous_genes, OBJ_SEQFEAT, sfp);
 
9906
  }
 
9907
  
 
9908
  CheckGenesForFeatureType (&features_without_genes, &superfluous_genes, bsp, 
 
9909
                            SEQFEAT_CDREGION, 0, TRUE);
 
9910
  CheckGenesForFeatureType (&features_without_genes, &superfluous_genes, bsp, 
 
9911
                            SEQFEAT_RNA, 0, TRUE);
 
9912
  CheckGenesForFeatureType (&features_without_genes, &superfluous_genes, bsp, 
 
9913
                            SEQFEAT_IMP, FEATDEF_RBS, FALSE);
 
9914
 
 
9915
  ValNodeLink (&(msgp->missing_list), features_without_genes);
 
9916
  ValNodeLink (&(msgp->super_list), superfluous_genes);
 
9917
}
 
9918
 
 
9919
 
 
9920
static void 
 
9921
GetPseudoAndNonPseudoGeneList 
 
9922
(ValNodePtr      super_list,
 
9923
 ValNodePtr PNTR pseudo_list, 
 
9924
 ValNodePtr PNTR non_pseudo_list)
 
9925
{
 
9926
  ValNodePtr vnp;
 
9927
  SeqFeatPtr gene;
 
9928
  GeneRefPtr grp;
 
9929
  
 
9930
  if (pseudo_list == NULL || non_pseudo_list == NULL)
 
9931
  {
 
9932
    return;
 
9933
  }
 
9934
  *pseudo_list = NULL;
 
9935
  *non_pseudo_list = NULL;
 
9936
  
 
9937
  for (vnp = super_list; vnp != NULL; vnp = vnp->next)
 
9938
  {
 
9939
    if (vnp->choice == OBJ_SEQFEAT)
 
9940
    {
 
9941
      gene = (SeqFeatPtr) vnp->data.ptrvalue;
 
9942
      if (gene != NULL && gene->data.choice == SEQFEAT_GENE)
 
9943
      {
 
9944
        grp = (GeneRefPtr) gene->data.value.ptrvalue;
 
9945
        if (gene->pseudo || (grp != NULL && grp->pseudo))
 
9946
        {
 
9947
          ValNodeAddPointer (pseudo_list, OBJ_SEQFEAT, gene);
 
9948
        }
 
9949
        else
 
9950
        {
 
9951
          ValNodeAddPointer (non_pseudo_list, OBJ_SEQFEAT, gene);
 
9952
        }
 
9953
      }
 
9954
    }
 
9955
  }
 
9956
}
 
9957
 
 
9958
 
 
9959
static void AddMissingAndSuperfluousGeneDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
9960
{
 
9961
  DiscrepancyItemPtr dip, pseudo_dip, non_pseudo_dip;
 
9962
  CharPtr            missing_genes_fmt = "%d features have no genes.";
 
9963
  CharPtr            extra_genes_fmt = "%d gene features are not associated with a CDS or RNA feature.";
 
9964
  CharPtr            pseudo_extra_genes_fmt = "%d pseudo gene features are not associated with a CDS or RNA feature.";
 
9965
  CharPtr            non_pseudo_extra_genes_fmt = "%d non-pseudo gene features are not associated with a CDS or RNA feature.";
 
9966
  MissSuperGenesData msgd;
 
9967
  ValNodePtr         non_pseudo_list = NULL, pseudo_list = NULL;
 
9968
 
 
9969
  if (discrepancy_list == NULL)
 
9970
  {
 
9971
    return;
 
9972
  }
 
9973
  
 
9974
  msgd.missing_list = NULL;
 
9975
  msgd.super_list = NULL;
 
9976
  
 
9977
  VisitBioseqsInSep (sep, &msgd, FindMissingGenes);
 
9978
  
 
9979
  if (msgd.missing_list != NULL)
 
9980
  {
 
9981
    dip = NewDiscrepancyItem (DISC_GENE_MISSING, missing_genes_fmt, msgd.missing_list);
 
9982
    if (dip != NULL)
 
9983
    {
 
9984
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
9985
    }
 
9986
  }
 
9987
  
 
9988
  if (msgd.super_list != NULL)
 
9989
  {
 
9990
    dip = NewDiscrepancyItem (DISC_SUPERFLUOUS_GENE, extra_genes_fmt, msgd.super_list);
 
9991
    if (dip != NULL)
 
9992
    {
 
9993
      ValNodeAddPointer (discrepancy_list, 0, dip);      
 
9994
      GetPseudoAndNonPseudoGeneList (msgd.super_list, &pseudo_list, &non_pseudo_list);
 
9995
      non_pseudo_dip = NewDiscrepancyItem (DISC_SUPERFLUOUS_GENE, non_pseudo_extra_genes_fmt, non_pseudo_list);
 
9996
      non_pseudo_dip->level = 1;
 
9997
      pseudo_dip = NewDiscrepancyItem (DISC_SUPERFLUOUS_GENE, pseudo_extra_genes_fmt, pseudo_list);
 
9998
      pseudo_dip->level = 1;
 
9999
      ValNodeAddPointer (&(dip->subcategories), 0, non_pseudo_dip);
 
10000
      ValNodeAddPointer (&(dip->subcategories), 0, pseudo_dip);
 
10001
    }
 
10002
  }  
 
10003
}
 
10004
 
 
10005
 
 
10006
typedef struct prefixcheck 
 
10007
{
 
10008
  CharPtr prefix;
 
10009
  ValNodePtr feature_list;
 
10010
} PrefixCheckData, PNTR PrefixCheckPtr;
 
10011
 
 
10012
 
 
10013
static ValNodePtr FreePrefixCheckList (ValNodePtr prefix_list)
 
10014
{
 
10015
  PrefixCheckPtr pcp;
 
10016
  
 
10017
  if (prefix_list == NULL)
 
10018
  {
 
10019
    return NULL;
 
10020
  }
 
10021
  
 
10022
  prefix_list->next = FreePrefixCheckList (prefix_list->next);
 
10023
  
 
10024
  pcp = (PrefixCheckPtr) prefix_list->data.ptrvalue;
 
10025
  if (pcp != NULL)
 
10026
  {
 
10027
    pcp->prefix = MemFree (pcp->prefix);
 
10028
    pcp->feature_list = ValNodeFree (pcp->feature_list);
 
10029
    pcp = MemFree (pcp);
 
10030
  }
 
10031
  prefix_list = ValNodeFree (prefix_list);
 
10032
  return NULL;
 
10033
}
 
10034
 
 
10035
 
 
10036
static DiscrepancyItemPtr InconsistentPrefix (PrefixCheckPtr pcp, CharPtr bad_fmt, DiscrepancyType disc_type)
 
10037
{
 
10038
  DiscrepancyItemPtr dip = NULL;
 
10039
 
 
10040
  if (pcp == NULL || StringHasNoText (pcp->prefix) || pcp->feature_list == NULL)
 
10041
  {
 
10042
    return NULL;
 
10043
  }
 
10044
  dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
10045
  if (dip != NULL)
 
10046
  {
 
10047
    dip->disc_type = DISC_GENE_LOCUS_TAG_INCONSISTENT_PREFIX;
 
10048
    dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + StringLen (pcp->prefix)+ 15));
 
10049
    sprintf (dip->description, bad_fmt, ValNodeLen (pcp->feature_list), pcp->prefix);
 
10050
    dip->callback_func = NULL;
 
10051
    dip->datafree_func = NULL;
 
10052
    dip->callback_data = NULL;
 
10053
    dip->item_list = pcp->feature_list;
 
10054
    pcp->feature_list = NULL;
 
10055
  }      
 
10056
  return dip;
 
10057
}
 
10058
 
 
10059
 
 
10060
static DiscrepancyItemPtr InconsistentLocusTagPrefix (PrefixCheckPtr pcp)
 
10061
{
 
10062
  CharPtr            bad_fmt = "%d features have locus tag prefix %s."; 
 
10063
 
 
10064
  return InconsistentPrefix (pcp, bad_fmt, DISC_GENE_LOCUS_TAG_INCONSISTENT_PREFIX);
 
10065
}
 
10066
 
 
10067
 
 
10068
static DiscrepancyItemPtr InconsistentProteinIDPrefix (PrefixCheckPtr pcp)
 
10069
{
 
10070
  CharPtr            bad_fmt = "%d sequences have protein ID prefix %s."; 
 
10071
 
 
10072
  return InconsistentPrefix (pcp, bad_fmt, DISC_INCONSISTENT_PROTEIN_ID_PREFIX);
 
10073
}
 
10074
 
 
10075
 
 
10076
typedef struct missinconstprotids 
 
10077
{
 
10078
  ValNodePtr missing_list;
 
10079
  ValNodePtr inconsistent_list;
 
10080
} MissInconstProtIDsData, PNTR MissInconstProtIDsPtr;
 
10081
 
 
10082
 
 
10083
static void FindMissingAndInconsistentProteinIDsCallback (BioseqPtr bsp, Pointer userdata)
 
10084
{
 
10085
  SeqIdPtr              sip;
 
10086
  MissInconstProtIDsPtr mipip;
 
10087
  DbtagPtr              dbt = NULL;
 
10088
  PrefixCheckPtr        pcp;
 
10089
  ValNodePtr            vnp;
 
10090
  
 
10091
  if (bsp == NULL || ! ISA_aa (bsp->mol) || userdata == NULL)
 
10092
  {
 
10093
    return;
 
10094
  }
 
10095
  
 
10096
  mipip = (MissInconstProtIDsPtr) userdata;
 
10097
  
 
10098
  for (sip = bsp->id; sip != NULL && dbt == NULL; sip = sip->next)
 
10099
  {
 
10100
    if (sip->choice == SEQID_GENERAL)
 
10101
    {
 
10102
      dbt = (DbtagPtr) sip->data.ptrvalue;
 
10103
      if (dbt != NULL && StringICmp (dbt->db, "TMSMART") == 0)
 
10104
      {
 
10105
        dbt = NULL;
 
10106
      }
 
10107
    }
 
10108
  }
 
10109
  if (dbt == NULL)
 
10110
  {
 
10111
    ValNodeAddPointer (&(mipip->missing_list), OBJ_BIOSEQ, bsp);
 
10112
  }
 
10113
  else
 
10114
  {  
 
10115
    /* look for inconsistent prefixes */
 
10116
    pcp = NULL;
 
10117
    for (vnp = mipip->inconsistent_list; vnp != NULL && pcp == NULL; vnp = vnp->next)
 
10118
    {
 
10119
      pcp = (PrefixCheckPtr) vnp->data.ptrvalue;
 
10120
      if (pcp != NULL && StringCmp (pcp->prefix, dbt->db) == 0)
 
10121
      {
 
10122
        ValNodeAddPointer (&pcp->feature_list, OBJ_BIOSEQ, bsp);
 
10123
      }
 
10124
      else
 
10125
      {
 
10126
        pcp = NULL;
 
10127
      }
 
10128
    }
 
10129
    if (pcp == NULL)
 
10130
    {
 
10131
      pcp = (PrefixCheckPtr) MemNew (sizeof (PrefixCheckData));
 
10132
      if (pcp != NULL)
 
10133
      {
 
10134
        pcp->prefix = StringSave (dbt->db);
 
10135
        pcp->feature_list = ValNodeNew (NULL);
 
10136
        pcp->feature_list->choice = OBJ_BIOSEQ;
 
10137
        pcp->feature_list->data.ptrvalue = bsp;
 
10138
        pcp->feature_list->next = NULL;
 
10139
        ValNodeAddPointer (&(mipip->inconsistent_list), 0, pcp);
 
10140
      }
 
10141
    }
 
10142
  }  
 
10143
}
 
10144
 
 
10145
 
 
10146
static void FindMissingProteinIDs (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
10147
{
 
10148
  CharPtr                bad_fmt = "%d proteins have invalid IDs.";
 
10149
  DiscrepancyItemPtr     dip;
 
10150
  MissInconstProtIDsData mipid;
 
10151
  ValNodePtr             vnp;
 
10152
  
 
10153
  if (discrepancy_list == NULL) return;
 
10154
  
 
10155
  mipid.missing_list = NULL;
 
10156
  mipid.inconsistent_list = NULL;
 
10157
  
 
10158
  VisitBioseqsInSep (sep, &mipid, FindMissingAndInconsistentProteinIDsCallback);
 
10159
  
 
10160
  if (mipid.missing_list != NULL)
 
10161
  {
 
10162
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
10163
    if (dip != NULL)
 
10164
    {
 
10165
      dip->disc_type = DISC_MISSING_PROTEIN_ID;
 
10166
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
10167
      sprintf (dip->description, bad_fmt, ValNodeLen (mipid.missing_list));
 
10168
      dip->callback_func = NULL;
 
10169
      dip->callback_data = NULL;
 
10170
      dip->datafree_func = NULL;
 
10171
      dip->item_list = mipid.missing_list;
 
10172
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
10173
    }
 
10174
  }
 
10175
  
 
10176
 
 
10177
  if (mipid.inconsistent_list != NULL)
 
10178
  {
 
10179
    if (mipid.inconsistent_list->next != NULL)
 
10180
    {
 
10181
      for (vnp = mipid.inconsistent_list; vnp != NULL; vnp = vnp->next)
 
10182
      {
 
10183
        dip = InconsistentProteinIDPrefix (vnp->data.ptrvalue);
 
10184
        if (dip != NULL)
 
10185
        {
 
10186
          ValNodeAddPointer (discrepancy_list, 0, dip);
 
10187
        }
 
10188
      }
 
10189
    }
 
10190
    mipid.inconsistent_list = FreePrefixCheckList (mipid.inconsistent_list);
 
10191
  }
 
10192
    
 
10193
}
 
10194
 
 
10195
typedef struct locustagcheck
 
10196
{
 
10197
  ValNodePtr locus_tags_list;
 
10198
  ValNodePtr missing_list;
 
10199
  ValNodePtr duplicate_list;
 
10200
  ValNodePtr bad_format_list;
 
10201
  ValNodePtr inconsistent_prefix;
 
10202
} LocusTagCheckData, PNTR LocusTagCheckPtr;
 
10203
 
 
10204
static void GeneLocusTagDiscrepancyCallback (ValNodePtr item_list, Pointer userdata)
 
10205
{
 
10206
  Message (MSG_OK, "I could launch the editor for the individual gene...");
 
10207
}
 
10208
 
 
10209
static Boolean IsLocusTagFormatBad (CharPtr locus_tag)
 
10210
{
 
10211
  CharPtr cp;
 
10212
  Boolean after_underscore = FALSE;
 
10213
  
 
10214
  if (StringHasNoText (locus_tag))
 
10215
  {
 
10216
    return FALSE;
 
10217
  }
 
10218
  
 
10219
  cp = locus_tag;
 
10220
  if (!isalpha (*cp))
 
10221
  {
 
10222
    return TRUE;
 
10223
  }
 
10224
  cp++;
 
10225
  while (*cp != 0)
 
10226
  {
 
10227
    if (*cp == '_')
 
10228
    {
 
10229
      if (after_underscore)
 
10230
      {
 
10231
        return TRUE;
 
10232
      }
 
10233
      else
 
10234
      {
 
10235
        after_underscore = TRUE;
 
10236
        if (*(cp + 1) == 0)
 
10237
        {
 
10238
          return TRUE;
 
10239
        }
 
10240
      }
 
10241
    }
 
10242
    else if (!isalpha (*cp) && !isdigit (*cp))
 
10243
    {
 
10244
      return TRUE;
 
10245
    }
 
10246
    cp++;
 
10247
  }
 
10248
  if (after_underscore)
 
10249
  {
 
10250
    return FALSE;
 
10251
  }
 
10252
  else
 
10253
  {
 
10254
    return TRUE;
 
10255
  }
 
10256
}
 
10257
 
 
10258
static CharPtr GetLocusTagPrefix (CharPtr locus_tag)
 
10259
{
 
10260
  Int4    prefix_len;
 
10261
  CharPtr prefix;
 
10262
  
 
10263
  if (StringHasNoText (locus_tag))
 
10264
  {
 
10265
    return NULL;
 
10266
  }
 
10267
  
 
10268
  prefix_len = StringCSpn (locus_tag, "_");
 
10269
  if (prefix_len == 0 || prefix_len == StringLen (locus_tag))
 
10270
  {
 
10271
    return NULL;
 
10272
  }
 
10273
  else
 
10274
  {
 
10275
    prefix = (CharPtr) MemNew ((prefix_len + 1) * sizeof (Char));
 
10276
    StringNCpy (prefix, locus_tag, prefix_len);
 
10277
    prefix [prefix_len] = 0;
 
10278
    return prefix;
 
10279
  }
 
10280
}
 
10281
 
 
10282
static void CheckGeneLocusTag (SeqFeatPtr sfp, Pointer userdata)
 
10283
{
 
10284
  GeneRefPtr         grp;
 
10285
  LocusTagCheckPtr   ltcp;
 
10286
  ValNodePtr         vnp;
 
10287
  Boolean            found_duplicate;
 
10288
  SeqFeatPtr         dup_sfp = NULL;
 
10289
  CharPtr            prefix;
 
10290
  PrefixCheckPtr     pcp;
 
10291
  
 
10292
  if (sfp == NULL || userdata == NULL || sfp->data.choice != SEQFEAT_GENE || sfp->data.value.ptrvalue == NULL)
 
10293
  {
 
10294
    return;
 
10295
  }
 
10296
  
 
10297
  ltcp = (LocusTagCheckPtr) userdata;
 
10298
  
 
10299
  grp = (GeneRefPtr) sfp->data.value.ptrvalue;
 
10300
  if (StringHasNoText (grp->locus_tag))
 
10301
  {
 
10302
    ValNodeAddPointer (&(ltcp->missing_list), OBJ_SEQFEAT, sfp);
 
10303
  }
 
10304
  else
 
10305
  {
 
10306
    /* look for badly formatted locus tags */
 
10307
    if (IsLocusTagFormatBad (grp->locus_tag))
 
10308
    {
 
10309
      ValNodeAddPointer (&(ltcp->bad_format_list), OBJ_SEQFEAT, sfp);
 
10310
    }
 
10311
    
 
10312
    /* look for inconsistent locus tag prefixes */
 
10313
    prefix = GetLocusTagPrefix (grp->locus_tag);
 
10314
    if (prefix != NULL)
 
10315
    {
 
10316
      pcp = NULL;
 
10317
      for (vnp = ltcp->inconsistent_prefix; vnp != NULL && pcp == NULL; vnp = vnp->next)
 
10318
      {
 
10319
        pcp = (PrefixCheckPtr) vnp->data.ptrvalue;
 
10320
        if (pcp != NULL && StringCmp (pcp->prefix, prefix) == 0)
 
10321
        {
 
10322
          ValNodeAddPointer (&pcp->feature_list, OBJ_SEQFEAT, sfp);
 
10323
          prefix = MemFree (prefix);
 
10324
        }
 
10325
        else
 
10326
        {
 
10327
          pcp = NULL;
 
10328
        }
 
10329
      }
 
10330
      if (pcp == NULL)
 
10331
      {
 
10332
        pcp = (PrefixCheckPtr) MemNew (sizeof (PrefixCheckData));
 
10333
        if (pcp != NULL)
 
10334
        {
 
10335
          pcp->prefix = prefix;
 
10336
          pcp->feature_list = ValNodeNew (NULL);
 
10337
          pcp->feature_list->choice = OBJ_SEQFEAT;
 
10338
          pcp->feature_list->data.ptrvalue = sfp;
 
10339
          pcp->feature_list->next = NULL;
 
10340
          ValNodeAddPointer (&(ltcp->inconsistent_prefix), 0, pcp);
 
10341
        }
 
10342
      }
 
10343
    }
 
10344
    
 
10345
  
 
10346
    dup_sfp = NULL;
 
10347
    for (vnp = ltcp->locus_tags_list, found_duplicate = FALSE;
 
10348
         vnp != NULL && !found_duplicate;
 
10349
         vnp = vnp->next)
 
10350
    { 
 
10351
      dup_sfp = (SeqFeatPtr) vnp->data.ptrvalue;
 
10352
      if (dup_sfp != NULL && dup_sfp->data.choice == SEQFEAT_GENE)
 
10353
      {
 
10354
        grp = (GeneRefPtr) dup_sfp->data.value.ptrvalue;
 
10355
        if (grp != NULL && StringCmp (vnp->data.ptrvalue, grp->locus_tag) == 0)
 
10356
        {
 
10357
          found_duplicate = TRUE;
 
10358
          if (vnp->choice != 0)
 
10359
          {
 
10360
            dup_sfp = NULL;
 
10361
          }
 
10362
          else
 
10363
          {
 
10364
            vnp->choice = 1;
 
10365
          }
 
10366
        }
 
10367
        else
 
10368
        {
 
10369
          dup_sfp = NULL;
 
10370
        }
 
10371
      }
 
10372
      else
 
10373
      {
 
10374
        dup_sfp = NULL;
 
10375
      }
 
10376
    }
 
10377
    if (!found_duplicate)
 
10378
    {
 
10379
      ValNodeAddPointer (&(ltcp->locus_tags_list), 0, sfp);
 
10380
    }
 
10381
    else
 
10382
    {
 
10383
      if (dup_sfp != NULL)
 
10384
      {
 
10385
        ValNodeAddPointer (&(ltcp->duplicate_list), OBJ_SEQFEAT, dup_sfp);
 
10386
      }
 
10387
      ValNodeAddPointer (&(ltcp->duplicate_list), OBJ_SEQFEAT, sfp);
 
10388
    }
 
10389
  }
 
10390
}
 
10391
 
 
10392
static void AddDiscrepanciesForMissingOrNonUniqueGeneLocusTags (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
10393
{
 
10394
  LocusTagCheckData  ltcd;
 
10395
  DiscrepancyItemPtr dip = NULL;
 
10396
  CharPtr            missing_fmt = "%d genes have no locus tags.";
 
10397
  CharPtr            duplicate_fmt = "%d genes have duplicate locus tags.";
 
10398
  CharPtr            bad_fmt = "%d locus tags are incorrectly formatted.";
 
10399
  ValNodePtr         vnp;
 
10400
  
 
10401
  if (discrepancy_list == NULL) return;
 
10402
  ltcd.locus_tags_list = NULL;
 
10403
  ltcd.missing_list = NULL;
 
10404
  ltcd.duplicate_list = NULL;
 
10405
  ltcd.bad_format_list = NULL;
 
10406
  ltcd.inconsistent_prefix = NULL;
 
10407
  
 
10408
  VisitFeaturesInSep (sep, &ltcd, CheckGeneLocusTag);
 
10409
  ltcd.locus_tags_list = ValNodeFree (ltcd.locus_tags_list);
 
10410
  
 
10411
  if (ltcd.missing_list != NULL)
 
10412
  {
 
10413
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
10414
    if (dip != NULL)
 
10415
    {
 
10416
      dip->disc_type = DISC_GENE_MISSING_LOCUS_TAG;
 
10417
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (missing_fmt) + 15));
 
10418
      sprintf (dip->description, missing_fmt, ValNodeLen (ltcd.missing_list));
 
10419
      dip->callback_func = GeneLocusTagDiscrepancyCallback;
 
10420
      dip->datafree_func = NULL;
 
10421
      dip->callback_data = NULL;
 
10422
      dip->item_list = ltcd.missing_list;
 
10423
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
10424
    }
 
10425
  }
 
10426
  
 
10427
  if (ltcd.duplicate_list != NULL)
 
10428
  {
 
10429
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
10430
    if (dip != NULL)
 
10431
    {
 
10432
      dip->disc_type = DISC_GENE_DUPLICATE_LOCUS_TAG;
 
10433
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (duplicate_fmt) + 15));
 
10434
      sprintf (dip->description, duplicate_fmt, ValNodeLen (ltcd.duplicate_list));
 
10435
      dip->callback_func = GeneLocusTagDiscrepancyCallback;
 
10436
      dip->datafree_func = NULL;
 
10437
      dip->callback_data = NULL;
 
10438
      dip->item_list = ltcd.duplicate_list;
 
10439
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
10440
    }
 
10441
  } 
 
10442
  
 
10443
  if (ltcd.bad_format_list != NULL)
 
10444
  {
 
10445
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
10446
    if (dip != NULL)
 
10447
    {
 
10448
      dip->disc_type = DISC_GENE_LOCUS_TAG_BAD_FORMAT;
 
10449
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
10450
      sprintf (dip->description, bad_fmt, ValNodeLen (ltcd.bad_format_list));
 
10451
      dip->callback_func = NULL;
 
10452
      dip->datafree_func = NULL;
 
10453
      dip->callback_data = NULL;
 
10454
      dip->item_list = ltcd.bad_format_list;
 
10455
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
10456
    }
 
10457
  }
 
10458
  
 
10459
  if (ltcd.inconsistent_prefix != NULL)
 
10460
  {
 
10461
    if (ltcd.inconsistent_prefix->next != NULL)
 
10462
    {
 
10463
      for (vnp = ltcd.inconsistent_prefix; vnp != NULL; vnp = vnp->next)
 
10464
      {
 
10465
        dip = InconsistentLocusTagPrefix (vnp->data.ptrvalue);
 
10466
        if (dip != NULL)
 
10467
        {
 
10468
          ValNodeAddPointer (discrepancy_list, 0, dip);
 
10469
        }
 
10470
      }
 
10471
    }
 
10472
    ltcd.inconsistent_prefix = FreePrefixCheckList (ltcd.inconsistent_prefix);
 
10473
  }
 
10474
}
 
10475
 
 
10476
static void NonGeneLocusTagDiscrepancyCallback (ValNodePtr item_list, Pointer userdata)
 
10477
{
 
10478
  Message (MSG_OK, "I could launch the editor for the individual gene, or I could remove all non-gene locus tags, or I could convert all non-gene locus tags to notes...");
 
10479
}
 
10480
 
 
10481
static void AddDiscrepancyForNonGeneLocusTag (SeqFeatPtr sfp, Pointer userdata)
 
10482
{
 
10483
  ValNodePtr PNTR    locus_tag_list;
 
10484
  GBQualPtr          qual;
 
10485
  
 
10486
  if (sfp == NULL || userdata == NULL || sfp->data.choice == SEQFEAT_GENE)
 
10487
  {
 
10488
    return;
 
10489
  }
 
10490
  
 
10491
  locus_tag_list = (ValNodePtr PNTR) userdata;
 
10492
  
 
10493
  for (qual = sfp->qual; qual != NULL; qual = qual->next)
 
10494
  {
 
10495
    if (StringICmp(qual->qual, "locus_tag") == 0) 
 
10496
    {
 
10497
      ValNodeAddPointer (locus_tag_list, OBJ_SEQFEAT, sfp);
 
10498
      return;
 
10499
    }
 
10500
  }
 
10501
}
 
10502
 
 
10503
static void AddDiscrepanciesForNonGeneLocusTags (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
10504
{
 
10505
  ValNodePtr locus_tag_list = NULL;
 
10506
  CharPtr    bad_fmt = "%d non-gene features have locus tags.";
 
10507
  DiscrepancyItemPtr dip;
 
10508
  
 
10509
  VisitFeaturesInSep (sep, &locus_tag_list, AddDiscrepancyForNonGeneLocusTag);
 
10510
  if (locus_tag_list != NULL)
 
10511
  {
 
10512
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
10513
    if (dip != NULL)
 
10514
    {
 
10515
      dip->disc_type = DISC_NON_GENE_LOCUS_TAG;
 
10516
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
10517
      sprintf (dip->description, bad_fmt, ValNodeLen (locus_tag_list));
 
10518
      dip->callback_func = NonGeneLocusTagDiscrepancyCallback;
 
10519
      dip->datafree_func = NULL;
 
10520
      dip->callback_data = NULL;
 
10521
      dip->item_list = locus_tag_list;
 
10522
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
10523
    }
 
10524
  }  
 
10525
}
 
10526
 
 
10527
 
 
10528
static Boolean 
 
10529
IsGeneLocationOk 
 
10530
(SeqMgrFeatContextPtr feat_context, 
 
10531
 SeqMgrFeatContextPtr gene_context,
 
10532
 BioseqPtr            bsp)
 
10533
{
 
10534
  SeqFeatPtr        rbs_sfp;
 
10535
  SeqMgrFeatContext rbs_context;
 
10536
  
 
10537
  if (feat_context == NULL || gene_context == NULL)
 
10538
  {
 
10539
    return FALSE;
 
10540
  }  
 
10541
  else if (feat_context->strand != gene_context->strand)
 
10542
  {
 
10543
    return FALSE;
 
10544
  }
 
10545
  else if (gene_context->left == feat_context->left && gene_context->right == feat_context->right)
 
10546
  {
 
10547
    return TRUE;
 
10548
  }
 
10549
  else if ((gene_context->strand == Seq_strand_minus && gene_context->left == feat_context->left)
 
10550
           || (gene_context->strand != Seq_strand_minus && gene_context->right == feat_context->right))
 
10551
  {
 
10552
    /* find RBS to extend gene on 5' end */
 
10553
    for (rbs_sfp = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_RBS, &rbs_context);
 
10554
         rbs_sfp != NULL;
 
10555
         rbs_sfp = SeqMgrGetNextFeature (bsp, rbs_sfp, 0, FEATDEF_RBS, &rbs_context))
 
10556
    {
 
10557
      if (rbs_context.strand != gene_context->strand)
 
10558
      {
 
10559
        continue;
 
10560
      }
 
10561
      if (rbs_context.strand == Seq_strand_minus)
 
10562
      {
 
10563
        if (rbs_context.right == gene_context->right 
 
10564
            && rbs_context.left >= feat_context->right)
 
10565
        {
 
10566
          return TRUE;
 
10567
        }
 
10568
      }
 
10569
      else
 
10570
      {
 
10571
        if (rbs_context.left == gene_context->left
 
10572
            && rbs_context.right <= feat_context->left)
 
10573
        {
 
10574
          return  TRUE;
 
10575
        }
 
10576
      }
 
10577
    }
 
10578
  }
 
10579
  return FALSE;
 
10580
}
 
10581
 
 
10582
static void
 
10583
CheckFeatureTypeForLocationDiscrepancies 
 
10584
(BioseqPtr       bsp, 
 
10585
 Uint2           feature_type,
 
10586
 ValNodePtr PNTR feature_list)
 
10587
{
 
10588
  SeqMgrFeatContext context, gene_context;
 
10589
  GeneRefPtr        grp;
 
10590
  SeqFeatPtr        sfp, gene_sfp;
 
10591
  ValNodePtr        found_genes = NULL;
 
10592
  Boolean           found_match;
 
10593
  
 
10594
  if (bsp == NULL || ISA_aa (bsp->mol) || feature_list == NULL)
 
10595
  {
 
10596
    return;
 
10597
  }
 
10598
 
 
10599
  for (sfp = SeqMgrGetNextFeature (bsp, NULL, feature_type, 0, &context);
 
10600
       sfp != NULL;
 
10601
       sfp = SeqMgrGetNextFeature (bsp, sfp, feature_type, 0, &context))
 
10602
  {
 
10603
    grp = SeqMgrGetGeneXref (sfp);
 
10604
    if (grp == NULL)
 
10605
    {
 
10606
      gene_sfp = SeqMgrGetOverlappingGene (sfp->location, &gene_context);
 
10607
      if (gene_sfp != NULL && !IsGeneLocationOk (&context, &gene_context, bsp))
 
10608
      {
 
10609
        ValNodeAddPointer (feature_list, OBJ_SEQFEAT, sfp);
 
10610
        ValNodeAddPointer (feature_list, OBJ_SEQFEAT, gene_sfp);
 
10611
      }
 
10612
    }
 
10613
    else if (!SeqMgrGeneIsSuppressed (grp))
 
10614
    {
 
10615
      found_match = FALSE;
 
10616
      for (gene_sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_GENE, FEATDEF_GENE, &gene_context);
 
10617
           gene_sfp != NULL && ! found_match;
 
10618
           gene_sfp = SeqMgrGetNextFeature (bsp, gene_sfp, SEQFEAT_GENE, FEATDEF_GENE, &gene_context))
 
10619
      {
 
10620
        if (GeneRefMatch (gene_sfp->data.value.ptrvalue, grp) && gene_context.strand == context.strand)
 
10621
        {
 
10622
          if (IsGeneLocationOk (&context, &gene_context, bsp))
 
10623
          {
 
10624
            found_match = TRUE;
 
10625
          }
 
10626
          else
 
10627
          {
 
10628
            ValNodeAddPointer (&found_genes, OBJ_SEQFEAT, gene_sfp);
 
10629
          }
 
10630
        }
 
10631
      }
 
10632
      if (found_match || found_genes == NULL)
 
10633
      {
 
10634
        found_genes = ValNodeFree (found_genes);
 
10635
        continue;
 
10636
      }
 
10637
      ValNodeAddPointer (feature_list, OBJ_SEQFEAT, sfp);
 
10638
      ValNodeLink (feature_list, found_genes);
 
10639
    }
 
10640
  }
 
10641
  
 
10642
}
 
10643
 
 
10644
static void CDSmRNAGeneLocationDiscrepanciesCallback (BioseqPtr bsp, Pointer userdata)
 
10645
{
 
10646
  ValNodePtr PNTR   feature_list;
 
10647
 
 
10648
  if (bsp == NULL || ! ISA_na (bsp->mol) || userdata == NULL)
 
10649
  {
 
10650
    return;
 
10651
  }
 
10652
  
 
10653
  feature_list = (ValNodePtr PNTR) userdata;
 
10654
  
 
10655
  CheckFeatureTypeForLocationDiscrepancies (bsp, SEQFEAT_CDREGION, feature_list);
 
10656
  CheckFeatureTypeForLocationDiscrepancies (bsp, SEQFEAT_RNA, feature_list);
 
10657
}
 
10658
 
 
10659
 
 
10660
static void FindCDSmRNAGeneLocationDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
10661
{
 
10662
  ValNodePtr feature_list = NULL;
 
10663
  CharPtr            bad_fmt = "%d coding regions, mRNAs, and genes have inconsistent locations.";
 
10664
  DiscrepancyItemPtr dip;
 
10665
  
 
10666
  VisitBioseqsInSep (sep, &feature_list, CDSmRNAGeneLocationDiscrepanciesCallback);
 
10667
  
 
10668
  if (feature_list != NULL)
 
10669
  {
 
10670
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
10671
    if (dip != NULL)
 
10672
    {
 
10673
      dip->disc_type = DISC_GENE_CDS_mRNA_LOCATION_CONFLICT;
 
10674
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
10675
      sprintf (dip->description, bad_fmt, ValNodeLen (feature_list));
 
10676
      dip->callback_func = NULL;
 
10677
      dip->datafree_func = NULL;
 
10678
      dip->callback_data = NULL;
 
10679
      dip->item_list = feature_list;
 
10680
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
10681
    }
 
10682
  }  
 
10683
}
 
10684
 
 
10685
 
 
10686
typedef struct cdsgeneproduct 
 
10687
{
 
10688
  SeqFeatPtr cds;
 
10689
  CharPtr    gene_locus;
 
10690
  CharPtr    product_name;
 
10691
} CDSGeneProductData, PNTR CDSGeneProductPtr;
 
10692
 
 
10693
 
 
10694
static CharPtr GetGeneLabel (SeqFeatPtr sfp)
 
10695
{
 
10696
  GeneRefPtr grp;
 
10697
  SeqFeatPtr gene_sfp;
 
10698
  
 
10699
  grp = SeqMgrGetGeneXref (sfp);
 
10700
  if (grp == NULL)
 
10701
  {
 
10702
    gene_sfp = SeqMgrGetOverlappingGene (sfp->location, NULL);
 
10703
    if (gene_sfp != NULL)
 
10704
    {
 
10705
      grp = gene_sfp->data.value.ptrvalue;
 
10706
    }
 
10707
  }
 
10708
  if (grp != NULL)
 
10709
  {
 
10710
    if (!StringHasNoText (grp->locus))
 
10711
    {
 
10712
      return grp->locus;
 
10713
    }
 
10714
  }
 
10715
  return NULL;
 
10716
}
 
10717
 
 
10718
static void FindCDSGeneProductConflictsCallback (SeqFeatPtr sfp, Pointer userdata)
 
10719
{
 
10720
  CDSGeneProductPtr cgpp, cgpp_compare;
 
10721
  SeqMgrFeatContext context;
 
10722
  ValNodePtr PNTR   cds_list;
 
10723
  ValNodePtr        prev = NULL, vnp;
 
10724
  Boolean           found_match = FALSE;
 
10725
  Uint1             new_choice = 0;
 
10726
  CharPtr           gene_label;
 
10727
  
 
10728
  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION || userdata == NULL)
 
10729
  {
 
10730
    return;
 
10731
  }
 
10732
  
 
10733
  sfp = SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL, 0, 0, sfp, &context);
 
10734
  if (sfp == NULL)
 
10735
  {
 
10736
    return;
 
10737
  }
 
10738
  
 
10739
  gene_label = GetGeneLabel (sfp);
 
10740
  if (StringHasNoText (gene_label)) return;
 
10741
  
 
10742
  cgpp = (CDSGeneProductPtr) MemNew (sizeof (CDSGeneProductData));
 
10743
  if (cgpp != NULL)
 
10744
  {
 
10745
    cgpp->cds = sfp;
 
10746
    cgpp->gene_locus = gene_label;
 
10747
    cgpp->product_name = StringSave (context.label);
 
10748
    
 
10749
    cds_list = (ValNodePtr PNTR) userdata;
 
10750
    if (*cds_list == NULL)
 
10751
    {
 
10752
      ValNodeAddPointer (cds_list, 0, cgpp);
 
10753
    }
 
10754
    else
 
10755
    {
 
10756
      vnp = *cds_list;
 
10757
      while (vnp != NULL && !found_match)
 
10758
      {
 
10759
        cgpp_compare = (CDSGeneProductPtr) vnp->data.ptrvalue;
 
10760
        if (cgpp_compare != NULL 
 
10761
            && StringCmp (cgpp_compare->gene_locus, cgpp->gene_locus) == 0
 
10762
            && StringCmp (cgpp_compare->product_name, cgpp->product_name) != 0)
 
10763
        {
 
10764
          found_match = TRUE;
 
10765
          vnp->choice = 1;
 
10766
          new_choice = 1;
 
10767
        }
 
10768
        prev = vnp;
 
10769
        vnp = vnp->next;
 
10770
      }
 
10771
      
 
10772
      if (found_match)
 
10773
      {
 
10774
        vnp = prev;
 
10775
        /* insert at end of matches */
 
10776
        while (found_match && vnp != NULL)
 
10777
        {
 
10778
          cgpp_compare = (CDSGeneProductPtr) vnp->data.ptrvalue;
 
10779
          if (cgpp_compare != NULL 
 
10780
            && StringCmp (cgpp_compare->gene_locus, cgpp->gene_locus) != 0)
 
10781
          {
 
10782
            found_match = FALSE;
 
10783
          }
 
10784
          else
 
10785
          {
 
10786
            prev = vnp;
 
10787
          }
 
10788
          vnp = vnp->next;
 
10789
        }
 
10790
      }
 
10791
 
 
10792
      /* add to list */
 
10793
      vnp = ValNodeNew (NULL);
 
10794
      vnp->choice = new_choice;
 
10795
      vnp->data.ptrvalue = cgpp;
 
10796
      vnp->next = prev->next;
 
10797
      prev->next = vnp;
 
10798
      
 
10799
    }
 
10800
  }
 
10801
}
 
10802
 
 
10803
static void FindCDSGeneProductConflicts (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
10804
{
 
10805
  ValNodePtr         cds_list = NULL, non_conflict = NULL, vnp;
 
10806
  CDSGeneProductPtr  cgpp;
 
10807
  CharPtr            bad_fmt = "%d coding regions have the same gene name as another coding region but a different product.";
 
10808
  DiscrepancyItemPtr dip;
 
10809
  
 
10810
  VisitFeaturesInSep (sep, &cds_list, FindCDSGeneProductConflictsCallback);
 
10811
 
 
10812
  /* remove CDSs without conflicts */
 
10813
  non_conflict = ValNodeExtractList (&cds_list, 0);
 
10814
  non_conflict = ValNodeFree (non_conflict);
 
10815
  
 
10816
  /* for each item, replace structure used for search with just the feature */
 
10817
  for (vnp = cds_list; vnp != NULL; vnp = vnp->next)
 
10818
  {
 
10819
    cgpp = (CDSGeneProductPtr) vnp->data.ptrvalue;
 
10820
    if (cgpp != NULL)
 
10821
    {
 
10822
      vnp->data.ptrvalue = cgpp->cds;
 
10823
      vnp->choice = OBJ_SEQFEAT;
 
10824
      cgpp->product_name = MemFree (cgpp->product_name);
 
10825
      /* note - we are not freeing gene_locus because we didn't make a copy */
 
10826
      cgpp = MemFree (cgpp);
 
10827
    }
 
10828
  }
 
10829
    
 
10830
  if (cds_list != NULL)
 
10831
  {
 
10832
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
10833
    if (dip != NULL)
 
10834
    {
 
10835
      dip->disc_type = DISC_GENE_PRODUCT_CONFLICT;
 
10836
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
10837
      sprintf (dip->description, bad_fmt, ValNodeLen (cds_list));
 
10838
      dip->callback_func = NULL;
 
10839
      dip->datafree_func = NULL;
 
10840
      dip->callback_data = NULL;
 
10841
      dip->item_list = cds_list;
 
10842
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
10843
    }
 
10844
  }  
 
10845
}
 
10846
 
 
10847
 
 
10848
static void DuplicateGeneLocusCallback (SeqFeatPtr sfp, Pointer userdata)
 
10849
{
 
10850
  ValNodePtr PNTR gene_list;
 
10851
  SeqFeatPtr      sfp_compare;
 
10852
  GeneRefPtr      grp, grp_compare;
 
10853
  ValNodePtr      prev = NULL, vnp;
 
10854
  Boolean         found_match = FALSE;
 
10855
  Uint1           new_choice = 0;
 
10856
  
 
10857
  if (sfp == NULL || sfp->data.choice != SEQFEAT_GENE || sfp->data.value.ptrvalue == NULL
 
10858
      || userdata == NULL)
 
10859
  {
 
10860
    return;
 
10861
  }
 
10862
  
 
10863
  gene_list = (ValNodePtr PNTR) userdata;
 
10864
  grp = (GeneRefPtr) sfp->data.value.ptrvalue;
 
10865
  if (StringHasNoText (grp->locus))
 
10866
  {
 
10867
    return;
 
10868
  }
 
10869
  
 
10870
  if (*gene_list == NULL)
 
10871
  {
 
10872
    ValNodeAddPointer (gene_list, 0, sfp);
 
10873
  }
 
10874
  else
 
10875
  {
 
10876
    vnp = *gene_list;
 
10877
    while (vnp != NULL && !found_match)
 
10878
    {
 
10879
      sfp_compare = (SeqFeatPtr) vnp->data.ptrvalue;
 
10880
      grp_compare = (GeneRefPtr) sfp_compare->data.value.ptrvalue;
 
10881
      if (StringCmp (grp_compare->locus, grp->locus) == 0)
 
10882
      {
 
10883
        found_match = TRUE;
 
10884
        vnp->choice = OBJ_SEQFEAT;
 
10885
        new_choice = OBJ_SEQFEAT;
 
10886
      }
 
10887
      prev = vnp;
 
10888
      vnp = vnp->next;
 
10889
    }
 
10890
    
 
10891
    if (found_match)
 
10892
    {
 
10893
      vnp = prev;
 
10894
      /* insert at end of matches */
 
10895
      while (found_match && vnp != NULL)
 
10896
      {
 
10897
        sfp_compare = (SeqFeatPtr) vnp->data.ptrvalue;
 
10898
        grp_compare = (GeneRefPtr) sfp_compare->data.value.ptrvalue;
 
10899
        if (StringCmp (grp_compare->locus, grp->locus) != 0)
 
10900
        {
 
10901
          found_match = FALSE;
 
10902
        }
 
10903
        else
 
10904
        {
 
10905
          prev = vnp;
 
10906
        }
 
10907
        vnp = vnp->next;
 
10908
      }
 
10909
    }
 
10910
 
 
10911
    /* add to list */
 
10912
    vnp = ValNodeNew (NULL);
 
10913
    vnp->choice = new_choice;
 
10914
    vnp->data.ptrvalue = sfp;
 
10915
    vnp->next = prev->next;
 
10916
    prev->next = vnp;
 
10917
      
 
10918
  }
 
10919
  
 
10920
}
 
10921
 
 
10922
 
 
10923
static void FindDuplicateGeneLocus (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
10924
{
 
10925
  ValNodePtr         gene_list = NULL, non_conflict = NULL;
 
10926
  CharPtr            bad_fmt = "%d genes have the same locus as another gene.";
 
10927
  DiscrepancyItemPtr dip;
 
10928
  
 
10929
  VisitFeaturesInSep (sep, &gene_list, DuplicateGeneLocusCallback);
 
10930
 
 
10931
  /* remove Genes without conflicts */
 
10932
  non_conflict = ValNodeExtractList (&gene_list, 0);
 
10933
  non_conflict = ValNodeFree (non_conflict);
 
10934
  
 
10935
  if (gene_list != NULL)
 
10936
  {
 
10937
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
10938
    if (dip != NULL)
 
10939
    {
 
10940
      dip->disc_type = DISC_GENE_DUPLICATE_LOCUS;
 
10941
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
10942
      sprintf (dip->description, bad_fmt, ValNodeLen (gene_list));
 
10943
      dip->callback_func = NULL;
 
10944
      dip->datafree_func = NULL;
 
10945
      dip->callback_data = NULL;
 
10946
      dip->item_list = gene_list;
 
10947
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
10948
    }
 
10949
  }  
 
10950
  
 
10951
}
 
10952
 
 
10953
 
 
10954
static void ECNumberNoteDiscrepancyCallback (ValNodePtr item_list, Pointer userdata)
 
10955
{
 
10956
  Message (MSG_OK, "I could launch the editor for the individual feature, or I could convert the note to an EC number qual");
 
10957
}
 
10958
 
 
10959
 
 
10960
static Boolean ECNumberInText (CharPtr text) 
 
10961
{
 
10962
  CharPtr cp_num, cp_dash, cp_start;
 
10963
  Int4    nums_found = 0;
 
10964
  
 
10965
  if (StringHasNoText (text)) {
 
10966
      return FALSE;
 
10967
  }
 
10968
  
 
10969
  cp_num = text + StrCSpn (text, "1234567890");
 
10970
  cp_dash = StringStr (text, "-");
 
10971
  if (cp_dash == NULL || cp_dash > cp_num) {
 
10972
    cp_start = cp_num;
 
10973
  } else {
 
10974
    cp_start = cp_dash;
 
10975
  }
 
10976
  
 
10977
  while (*cp_start != 0) {
 
10978
    nums_found++;
 
10979
    while (isdigit (*cp_start) || *cp_start == '-') {
 
10980
      cp_start++;
 
10981
    }
 
10982
    if (*cp_start != '.') {
 
10983
      if (nums_found == 4) {
 
10984
        return TRUE;
 
10985
      } else {
 
10986
        return ECNumberInText (cp_start);
 
10987
      }
 
10988
    } else {
 
10989
      cp_start ++;
 
10990
    }
 
10991
  }    
 
10992
  if (nums_found == 4) {
 
10993
    return TRUE;
 
10994
  } else {
 
10995
    return FALSE;
 
10996
  }
 
10997
}
 
10998
 
 
10999
 
 
11000
static void FindECNumberNotes (SeqFeatPtr sfp, Pointer userdata)
 
11001
{
 
11002
  ValNodePtr PNTR    ec_number_features;
 
11003
  BioseqPtr          prot_bsp;
 
11004
  SeqMgrFeatContext  fcontext;
 
11005
  SeqFeatPtr         prot_sfp;
 
11006
  ProtRefPtr         prp;
 
11007
  ValNodePtr         vnp;
 
11008
  
 
11009
  if (sfp == NULL || userdata == NULL || StringHasNoText (sfp->comment))
 
11010
  {
 
11011
    return;
 
11012
  }
 
11013
  
 
11014
  ec_number_features = (ValNodePtr PNTR) userdata;
 
11015
  
 
11016
  if (ECNumberInText (sfp->comment))
 
11017
  {
 
11018
    ValNodeAddPointer (ec_number_features, OBJ_SEQFEAT, sfp);
 
11019
  }
 
11020
  else if (sfp->data.choice == SEQFEAT_CDREGION && sfp->product != NULL) 
 
11021
  {
 
11022
    prot_bsp = BioseqFindFromSeqLoc(sfp->product);
 
11023
    prot_sfp = SeqMgrGetNextFeature(prot_bsp, NULL, SEQFEAT_PROT, FEATDEF_PROT, &fcontext);
 
11024
    if (prot_sfp != NULL && prot_sfp->data.value.ptrvalue != NULL) {
 
11025
      prp = (ProtRefPtr) prot_sfp->data.value.ptrvalue;
 
11026
      for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
 
11027
        if (ECNumberInText (vnp->data.ptrvalue)) {
 
11028
          ValNodeAddPointer (ec_number_features, OBJ_SEQFEAT, sfp);
 
11029
          return;
 
11030
        }
 
11031
      }
 
11032
      if (ECNumberInText (prp->desc)) {
 
11033
        ValNodeAddPointer (ec_number_features, OBJ_SEQFEAT, sfp);
 
11034
        return;
 
11035
      }
 
11036
    }
 
11037
  }  
 
11038
}
 
11039
 
 
11040
static void AddECNumberNoteDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
11041
{
 
11042
  ValNodePtr ec_number_features = NULL;
 
11043
  DiscrepancyItemPtr dip;
 
11044
  CharPtr            bad_fmt = "%d features have EC numbers in notes or products.";
 
11045
  
 
11046
  if (discrepancy_list == NULL) return;
 
11047
  
 
11048
  VisitFeaturesInSep (sep, &ec_number_features, FindECNumberNotes);
 
11049
  
 
11050
  if (ec_number_features != NULL)
 
11051
  {
 
11052
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
11053
    if (dip != NULL)
 
11054
    {
 
11055
      dip->disc_type = DISC_EC_NUMBER_NOTE;
 
11056
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
11057
      sprintf (dip->description, bad_fmt, ValNodeLen (ec_number_features));
 
11058
      dip->callback_func = ECNumberNoteDiscrepancyCallback;
 
11059
      dip->datafree_func = NULL;
 
11060
      dip->callback_data = NULL;
 
11061
      dip->item_list = ec_number_features;
 
11062
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
11063
    }
 
11064
  }
 
11065
  
 
11066
}
 
11067
 
 
11068
 
 
11069
static void FindPseudoDiscrepanciesCallback (SeqFeatPtr sfp, Pointer userdata)
 
11070
{
 
11071
  ValNodePtr PNTR pseudo_features;
 
11072
  GeneRefPtr      grp;
 
11073
  SeqFeatPtr      gene_sfp = NULL;
 
11074
  Boolean         found_conflict = FALSE;
 
11075
  
 
11076
  if (sfp == NULL || (sfp->data.choice != SEQFEAT_CDREGION && sfp->data.choice != SEQFEAT_RNA)
 
11077
      || userdata == NULL)
 
11078
  {
 
11079
    return;
 
11080
  }
 
11081
  
 
11082
  grp = SeqMgrGetGeneXref (sfp);
 
11083
  if (grp != NULL)
 
11084
  {
 
11085
    return;
 
11086
  }
 
11087
  
 
11088
  gene_sfp = SeqMgrGetOverlappingGene (sfp->location, NULL);
 
11089
  if (gene_sfp == NULL)
 
11090
  {
 
11091
    return;
 
11092
  }
 
11093
  
 
11094
  if ((sfp->pseudo && ! gene_sfp->pseudo)
 
11095
      || (!sfp->pseudo && gene_sfp->pseudo))
 
11096
  {
 
11097
    pseudo_features = (ValNodePtr PNTR) userdata;
 
11098
    ValNodeAddPointer (pseudo_features, OBJ_SEQFEAT, sfp);
 
11099
    if (gene_sfp != NULL)
 
11100
    {
 
11101
      ValNodeAddPointer (pseudo_features, OBJ_SEQFEAT, gene_sfp);
 
11102
    }
 
11103
  }
 
11104
}
 
11105
 
 
11106
 
 
11107
static void FindPseudoDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
11108
{
 
11109
  ValNodePtr pseudo_features = NULL;
 
11110
  DiscrepancyItemPtr dip;
 
11111
  CharPtr            bad_fmt = "%d CDSs, RNAs, and genes have mismatching pseudos.";
 
11112
  
 
11113
  if (discrepancy_list == NULL) return;
 
11114
  
 
11115
  VisitFeaturesInSep (sep, &pseudo_features, FindPseudoDiscrepanciesCallback);
 
11116
  
 
11117
  if (pseudo_features != NULL)
 
11118
  {
 
11119
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
11120
    if (dip != NULL)
 
11121
    {
 
11122
      dip->disc_type = DISC_PSEUDO_MISMATCH;
 
11123
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
11124
      sprintf (dip->description, bad_fmt, ValNodeLen (pseudo_features));
 
11125
      dip->callback_func = NULL;
 
11126
      dip->datafree_func = NULL;
 
11127
      dip->callback_data = NULL;
 
11128
      dip->item_list = pseudo_features;
 
11129
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
11130
    }
 
11131
  }
 
11132
  
 
11133
}
 
11134
 
 
11135
 
 
11136
static void FindJoinedLocations (SeqFeatPtr sfp, Pointer userdata)
 
11137
{
 
11138
  ValNodePtr PNTR joined_features;
 
11139
  
 
11140
  if (sfp == NULL || userdata == NULL || sfp->location == NULL)
 
11141
  {
 
11142
    return;
 
11143
  }
 
11144
  
 
11145
  joined_features = (ValNodePtr PNTR) userdata;
 
11146
  if (sfp->location->choice == SEQLOC_MIX)
 
11147
  {
 
11148
    ValNodeAddPointer (joined_features, OBJ_SEQFEAT, sfp);
 
11149
  }
 
11150
}
 
11151
 
 
11152
static void AddJoinedFeatureDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
11153
{
 
11154
  ValNodePtr joined_features = NULL;
 
11155
  
 
11156
  DiscrepancyItemPtr dip;
 
11157
  CharPtr            bad_fmt = "%d features have joined locations.";
 
11158
  
 
11159
  if (discrepancy_list == NULL) return;
 
11160
  
 
11161
  VisitFeaturesInSep (sep, &joined_features, FindJoinedLocations);
 
11162
  
 
11163
  if (joined_features != NULL)
 
11164
  {
 
11165
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
11166
    if (dip != NULL)
 
11167
    {
 
11168
      dip->disc_type = DISC_JOINED_FEATURES;
 
11169
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
11170
      sprintf (dip->description, bad_fmt, ValNodeLen (joined_features));
 
11171
      dip->callback_func = NULL;
 
11172
      dip->datafree_func = NULL;
 
11173
      dip->callback_data = NULL;
 
11174
      dip->item_list = joined_features;
 
11175
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
11176
    }
 
11177
  }
 
11178
}
 
11179
 
 
11180
 
 
11181
static void FindOverlappingGenes (BioseqPtr bsp, Pointer userdata)
 
11182
{
 
11183
  SeqFeatPtr         sfp, sfp_compare;
 
11184
  SeqMgrFeatContext  context;
 
11185
  ValNodePtr PNTR    overlapping_genes = NULL, non_overlap;
 
11186
  ValNodePtr         gene_list = NULL, vnp, vnp_next;
 
11187
  
 
11188
  if (bsp == NULL || userdata == NULL)
 
11189
  {
 
11190
    return;
 
11191
  }
 
11192
  
 
11193
  overlapping_genes = (ValNodePtr PNTR) userdata;
 
11194
  
 
11195
  for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_GENE, FEATDEF_GENE, &context);
 
11196
       sfp != NULL;
 
11197
       sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_GENE, FEATDEF_GENE, &context))
 
11198
  {
 
11199
    ValNodeAddPointer (&gene_list, 0, sfp);
 
11200
  }
 
11201
  
 
11202
  for (vnp = gene_list; vnp != NULL && vnp->next != NULL; vnp = vnp->next)
 
11203
  {
 
11204
    sfp = (SeqFeatPtr) vnp->data.ptrvalue;
 
11205
    for (vnp_next = vnp->next; vnp_next != NULL; vnp_next = vnp_next->next)
 
11206
    {
 
11207
      sfp_compare = (SeqFeatPtr) vnp_next->data.ptrvalue;
 
11208
      
 
11209
      if (SeqLocStrand (sfp->location) != SeqLocStrand (sfp_compare->location))
 
11210
      {
 
11211
        continue;
 
11212
      }
 
11213
      
 
11214
      if (SeqLocCompare (sfp->location, sfp_compare->location) != SLC_NO_MATCH)
 
11215
      {
 
11216
        vnp->choice = OBJ_SEQFEAT;
 
11217
        vnp_next->choice = OBJ_SEQFEAT;
 
11218
      }
 
11219
    }
 
11220
  }
 
11221
  
 
11222
  non_overlap = ValNodeExtractList (&gene_list, 0);
 
11223
  non_overlap = ValNodeFree (non_overlap);
 
11224
  ValNodeLink (overlapping_genes, gene_list);
 
11225
  
 
11226
}
 
11227
 
 
11228
static void AddOverlappingGeneDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
11229
{
 
11230
  DiscrepancyItemPtr dip;
 
11231
  CharPtr            bad_fmt = "%d genes overlap another gene on the same strand.";
 
11232
  ValNodePtr         overlapping_genes = NULL;
 
11233
 
 
11234
  if (discrepancy_list == NULL)
 
11235
  {
 
11236
    return;
 
11237
  }
 
11238
  
 
11239
  VisitBioseqsInSep (sep, &overlapping_genes, FindOverlappingGenes);
 
11240
  
 
11241
  if (overlapping_genes != NULL)
 
11242
  {
 
11243
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
11244
    if (dip != NULL)
 
11245
    {
 
11246
      dip->disc_type = DISC_OVERLAPPING_GENES;
 
11247
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
11248
      sprintf (dip->description, bad_fmt, ValNodeLen (overlapping_genes));
 
11249
      dip->callback_func = NULL;
 
11250
      dip->datafree_func = NULL;
 
11251
      dip->callback_data = NULL;
 
11252
      dip->item_list = overlapping_genes;
 
11253
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
11254
    }
 
11255
  }
 
11256
}
 
11257
 
 
11258
 
 
11259
typedef struct cdsoverlap 
 
11260
{
 
11261
  CharPtr    product_name;
 
11262
  SeqFeatPtr sfp;  
 
11263
  Int4       left;
 
11264
  Int4       right;
 
11265
} CDSOverlapData, PNTR CDSOverlapPtr;
 
11266
 
 
11267
 
 
11268
static CDSOverlapPtr CDSOverlapNew (SeqFeatPtr sfp, CharPtr product_name, Int4 left, Int4 right)
 
11269
{
 
11270
  CDSOverlapPtr cop;
 
11271
  
 
11272
  cop = (CDSOverlapPtr) MemNew (sizeof (CDSOverlapData));
 
11273
  if (cop != NULL)
 
11274
  {
 
11275
    cop->product_name = StringSave (product_name);
 
11276
    cop->sfp = sfp;
 
11277
    cop->left = left;
 
11278
    cop->right = right;
 
11279
  }
 
11280
  return cop;
 
11281
}
 
11282
 
 
11283
 
 
11284
static ValNodePtr FreeCDSOverlapList (ValNodePtr vnp)
 
11285
{
 
11286
  CDSOverlapPtr cop;
 
11287
  
 
11288
  if (vnp != NULL)  
 
11289
  {
 
11290
    vnp->next = FreeCDSOverlapList (vnp->next);
 
11291
    cop = (CDSOverlapPtr) vnp->data.ptrvalue;
 
11292
    if (cop != NULL)
 
11293
    {
 
11294
      cop->product_name = MemFree (cop->product_name);
 
11295
      cop = MemFree (cop);
 
11296
      vnp->data.ptrvalue = NULL;
 
11297
    }
 
11298
    vnp = ValNodeFree (vnp);
 
11299
  }
 
11300
  return vnp;
 
11301
}
 
11302
 
 
11303
 
 
11304
static ValNodePtr FeatureListFromOverlapList (ValNodePtr vnp)
 
11305
{
 
11306
  ValNodePtr     feat_list = NULL;
 
11307
  CDSOverlapPtr cop;
 
11308
  
 
11309
  while (vnp != NULL)
 
11310
  {
 
11311
    if (vnp->choice != 0 && vnp->data.ptrvalue != NULL)
 
11312
    {
 
11313
      cop = (CDSOverlapPtr) vnp->data.ptrvalue;
 
11314
      ValNodeAddPointer (&feat_list, OBJ_SEQFEAT, cop->sfp);
 
11315
    }
 
11316
    vnp = vnp->next;
 
11317
  }
 
11318
  return feat_list;
 
11319
}
 
11320
 
 
11321
 
 
11322
static CharPtr similar_product_words[] = 
 
11323
{ "transposase",
 
11324
  "integrase"
 
11325
};
 
11326
 
 
11327
const int num_similar_product_words = sizeof (similar_product_words) / sizeof (CharPtr);
 
11328
 
 
11329
static CharPtr ignore_similar_product_words[] = 
 
11330
{ "hypothetical protein",
 
11331
  "phage"
 
11332
};
 
11333
 
 
11334
const int num_ignore_similar_product_words = sizeof (ignore_similar_product_words) / sizeof (CharPtr);
 
11335
 
 
11336
 
 
11337
static Boolean OverlappingProductNameSimilar (CharPtr str1, CharPtr str2)
 
11338
{
 
11339
  Int4 i;
 
11340
  Boolean str1_has_similarity_word = FALSE, str2_has_similarity_word = FALSE;
 
11341
  
 
11342
  if (StringHasNoText (str1) && StringHasNoText (str2))
 
11343
  {
 
11344
    return TRUE;
 
11345
  }
 
11346
  else if (StringHasNoText (str1) || StringHasNoText (str2))
 
11347
  {
 
11348
    return FALSE;
 
11349
  }
 
11350
  
 
11351
  /* if both product names contain one of the special case similarity words,
 
11352
   * the product names are similar. */
 
11353
  for (i = 0; i < num_similar_product_words; i++)
 
11354
  {
 
11355
    if (StringISearch (str1, similar_product_words [i]) != NULL)
 
11356
    {
 
11357
      str1_has_similarity_word = TRUE;
 
11358
    }
 
11359
    if (StringISearch (str2, similar_product_words [i]) != NULL)
 
11360
    {
 
11361
      str2_has_similarity_word = TRUE;
 
11362
    }
 
11363
  }
 
11364
  if (str1_has_similarity_word && str2_has_similarity_word)
 
11365
  {
 
11366
    return TRUE;
 
11367
  }
 
11368
  
 
11369
  /* otherwise, if one of the product names contains one of special ignore similarity
 
11370
   * words, the product names are not similar.
 
11371
   */
 
11372
  for (i = 0; i < num_ignore_similar_product_words; i++)
 
11373
  {
 
11374
    if (StringISearch (str1, ignore_similar_product_words[i]) != NULL
 
11375
        || StringISearch (str2, ignore_similar_product_words[i]) != NULL)
 
11376
    {
 
11377
      return FALSE;
 
11378
    }
 
11379
  }
 
11380
  
 
11381
  if (StringICmp (str1, str2) == 0)
 
11382
  {
 
11383
    return TRUE;
 
11384
  }
 
11385
  else
 
11386
  {
 
11387
    return FALSE;
 
11388
  }
 
11389
}
 
11390
 
 
11391
 
 
11392
static void FindOverlappingCDSs (BioseqPtr bsp, Pointer userdata)
 
11393
{
 
11394
  SeqFeatPtr         sfp;
 
11395
  SeqMgrFeatContext  context;
 
11396
  ValNodePtr PNTR    overlapping_cds = NULL, cds_list;
 
11397
  ValNodePtr         overlap_list = NULL, vnp, vnp_next;
 
11398
  CDSOverlapPtr      cop, cop_compare;
 
11399
  
 
11400
  if (bsp == NULL || userdata == NULL)
 
11401
  {
 
11402
    return;
 
11403
  }
 
11404
  
 
11405
  overlapping_cds = (ValNodePtr PNTR) userdata;
 
11406
  
 
11407
  for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, FEATDEF_CDS, &context);
 
11408
       sfp != NULL;
 
11409
       sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, FEATDEF_CDS, &context))
 
11410
  {
 
11411
    ValNodeAddPointer (&overlap_list, 0, CDSOverlapNew (sfp, context.label, context.left, context.right));
 
11412
  }
 
11413
  
 
11414
  for (vnp = overlap_list; vnp != NULL && vnp->next != NULL; vnp = vnp->next)
 
11415
  {
 
11416
    cop = (CDSOverlapPtr) vnp->data.ptrvalue;
 
11417
    if (cop == NULL)
 
11418
    {
 
11419
      continue;
 
11420
    }
 
11421
    for (vnp_next = vnp->next; vnp_next != NULL; vnp_next = vnp_next->next)
 
11422
    {
 
11423
      cop_compare = (CDSOverlapPtr) vnp_next->data.ptrvalue;
 
11424
      if (cop_compare == NULL)
 
11425
      {
 
11426
        continue;
 
11427
      }
 
11428
      else if (cop_compare->left > cop->right)
 
11429
      {
 
11430
        break;
 
11431
      }
 
11432
      if (!OverlappingProductNameSimilar (cop->product_name, cop_compare->product_name))
 
11433
      {
 
11434
        continue;
 
11435
      }
 
11436
      if (SeqLocStrand (cop->sfp->location) != SeqLocStrand (cop_compare->sfp->location))
 
11437
      {
 
11438
        continue;
 
11439
      }
 
11440
      
 
11441
      if (SeqLocCompare (cop->sfp->location, cop_compare->sfp->location) != SLC_NO_MATCH)
 
11442
      {
 
11443
        vnp->choice = OBJ_SEQFEAT;
 
11444
        vnp_next->choice = OBJ_SEQFEAT;
 
11445
      }
 
11446
    }
 
11447
  }
 
11448
  
 
11449
  cds_list = FeatureListFromOverlapList(overlap_list);
 
11450
  if (cds_list != NULL)
 
11451
  {
 
11452
    ValNodeLink (overlapping_cds, cds_list);
 
11453
  }
 
11454
  overlap_list = FreeCDSOverlapList (overlap_list);
 
11455
}
 
11456
 
 
11457
 
 
11458
static void AddOverlappingCodingRegionDiscrepancies (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
11459
{
 
11460
  DiscrepancyItemPtr dip;
 
11461
  CharPtr            bad_fmt = "%d coding regions overlap another coding region with a similar or identical name.";
 
11462
  ValNodePtr         overlapping_cds = NULL;
 
11463
 
 
11464
  if (discrepancy_list == NULL)
 
11465
  {
 
11466
    return;
 
11467
  }
 
11468
  
 
11469
  VisitBioseqsInSep (sep, &overlapping_cds, FindOverlappingCDSs);
 
11470
  
 
11471
  if (overlapping_cds != NULL)
 
11472
  {
 
11473
    dip = NewDiscrepancyItem (DISC_OVERLAPPING_CDS, bad_fmt, overlapping_cds);
 
11474
 
 
11475
    if (dip != NULL)
 
11476
    {
 
11477
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
11478
    }
 
11479
  }
 
11480
}
 
11481
 
 
11482
 
 
11483
static void FindShortContigsCallback (BioseqPtr bsp, Pointer userdata)
 
11484
{
 
11485
  ValNodePtr PNTR bioseq_list;
 
11486
  
 
11487
  if (bsp == NULL || !ISA_na (bsp->mol) || userdata == NULL || bsp->length >= 200)
 
11488
  {
 
11489
    return;
 
11490
  }
 
11491
  
 
11492
  bioseq_list = (ValNodePtr PNTR) userdata;
 
11493
  
 
11494
  ValNodeAddPointer (bioseq_list, OBJ_BIOSEQ, bsp);
 
11495
}
 
11496
 
 
11497
static void FindShortContigs (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
11498
{
 
11499
  DiscrepancyItemPtr dip;
 
11500
  CharPtr            bad_fmt = "%d contigs are shorter than 200 nt.";
 
11501
  ValNodePtr         bioseq_list = NULL;
 
11502
  
 
11503
  if (discrepancy_list == NULL) return;
 
11504
  
 
11505
  VisitBioseqsInSep (sep, &bioseq_list, FindShortContigsCallback);
 
11506
  
 
11507
  if (bioseq_list != NULL)
 
11508
  {
 
11509
    dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
11510
    if (dip != NULL)
 
11511
    {
 
11512
      dip->disc_type = DISC_SHORT_CONTIG;
 
11513
      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
11514
      sprintf (dip->description, bad_fmt, ValNodeLen (bioseq_list));
 
11515
      dip->callback_func = NULL;
 
11516
      dip->datafree_func = NULL;
 
11517
      dip->callback_data = NULL;
 
11518
      dip->item_list = bioseq_list;
 
11519
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
11520
    }
 
11521
  }
 
11522
}
 
11523
 
 
11524
typedef struct biosrccheck 
 
11525
{
 
11526
  BioSourcePtr biop;
 
11527
  ValNodePtr   sdp_list;
 
11528
} BioSrcCheckData, PNTR BioSrcCheckPtr;
 
11529
 
 
11530
static ValNodePtr FreeBioSrcCheckList (ValNodePtr biosrc_list)
 
11531
{
 
11532
  BioSrcCheckPtr  bscp;
 
11533
  
 
11534
  if (biosrc_list == NULL)
 
11535
  {
 
11536
    return NULL;
 
11537
  }
 
11538
  
 
11539
  biosrc_list->next = FreeBioSrcCheckList (biosrc_list->next);
 
11540
  
 
11541
  bscp = (BioSrcCheckPtr) biosrc_list->data.ptrvalue;
 
11542
  if (bscp != NULL)
 
11543
  {
 
11544
    bscp->sdp_list = ValNodeFree (bscp->sdp_list);
 
11545
    bscp = MemFree (bscp);
 
11546
  }
 
11547
  biosrc_list = ValNodeFree (biosrc_list);
 
11548
  return NULL;
 
11549
}
 
11550
 
 
11551
 
 
11552
static void FindInconsistentSourcesCallback (BioseqPtr bsp, Pointer userdata)
 
11553
{
 
11554
  ValNodePtr PNTR biosrc_list, vnp;
 
11555
  SeqDescrPtr     sdp;
 
11556
  BioSrcCheckPtr  bscp;
 
11557
  Boolean         found = FALSE;
 
11558
  SeqMgrDescContext context;
 
11559
  
 
11560
  if (bsp == NULL || !ISA_na (bsp->mol) || userdata == NULL)
 
11561
  {
 
11562
    return;
 
11563
  }
 
11564
  
 
11565
  biosrc_list = (ValNodePtr PNTR) userdata;
 
11566
  
 
11567
  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &context);
 
11568
  if (sdp != NULL)
 
11569
  {
 
11570
    for (vnp = *biosrc_list; vnp != NULL && !found; vnp = vnp->next)
 
11571
    {
 
11572
      bscp = (BioSrcCheckPtr) vnp->data.ptrvalue;
 
11573
      if (bscp != NULL && BioSourceMatch (sdp->data.ptrvalue, bscp->biop))
 
11574
      {
 
11575
        ValNodeAddPointer (&(bscp->sdp_list), OBJ_SEQDESC, sdp);
 
11576
        found = TRUE;
 
11577
      }
 
11578
    }
 
11579
    if (!found)
 
11580
    {
 
11581
      bscp = (BioSrcCheckPtr) MemNew (sizeof (BioSrcCheckData));
 
11582
      if (bscp != NULL)
 
11583
      {
 
11584
        bscp->biop = sdp->data.ptrvalue;
 
11585
        ValNodeAddPointer (&(bscp->sdp_list), OBJ_SEQDESC, sdp);
 
11586
        ValNodeAddPointer (biosrc_list, 0, bscp);
 
11587
      }
 
11588
    }
 
11589
  }
 
11590
}
 
11591
 
 
11592
 
 
11593
static DiscrepancyItemPtr InconsistentBiosrc (BioSrcCheckPtr bscp)
 
11594
{
 
11595
  DiscrepancyItemPtr dip = NULL;
 
11596
  CharPtr            bad_fmt = "%d contigs have identical sources that do not match another contig source.";
 
11597
 
 
11598
  if (bscp == NULL || bscp->sdp_list == NULL)
 
11599
  {
 
11600
    return NULL;
 
11601
  }
 
11602
  
 
11603
  dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
11604
  if (dip != NULL)
 
11605
  {
 
11606
    dip->disc_type = DISC_INCONSISTENT_BIOSRC;
 
11607
    dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
 
11608
    sprintf (dip->description, bad_fmt, ValNodeLen (bscp->sdp_list));
 
11609
    dip->callback_func = NULL;
 
11610
    dip->datafree_func = NULL;
 
11611
    dip->callback_data = NULL;
 
11612
    dip->item_list = bscp->sdp_list;
 
11613
    bscp->sdp_list = NULL;
 
11614
  }      
 
11615
  return dip;
 
11616
}
 
11617
 
 
11618
 
 
11619
static void FindNonmatchingContigSources (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
11620
{
 
11621
  DiscrepancyItemPtr dip;
 
11622
  ValNodePtr         biosrc_list = NULL, vnp;
 
11623
  
 
11624
  if (discrepancy_list == NULL) return;
 
11625
  
 
11626
  VisitBioseqsInSep (sep, &biosrc_list, FindInconsistentSourcesCallback);
 
11627
  
 
11628
  if (biosrc_list != NULL && biosrc_list->next != NULL)
 
11629
  {
 
11630
    for (vnp = biosrc_list; vnp != NULL; vnp = vnp->next)
 
11631
    {
 
11632
      dip = InconsistentBiosrc (vnp->data.ptrvalue);
 
11633
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
11634
    }
 
11635
  }
 
11636
  biosrc_list = FreeBioSrcCheckList (biosrc_list);
 
11637
}
 
11638
 
 
11639
 
 
11640
static CharPtr suspect_product_names[] = 
 
11641
{
 
11642
"Similar to",
 
11643
"Related to",
 
11644
"interrupt",
 
11645
"Homolog",
 
11646
"Homologue",
 
11647
"Fragment",
 
11648
"Frameshift",
 
11649
"Intein",
 
11650
"COG",
 
11651
"N-terminal",
 
11652
"N terminal",
 
11653
"C-terminal",
 
11654
"C terminal",
 
11655
"N-terminus",
 
11656
"C-terminus",
 
11657
"Chloroplast",
 
11658
"Mitochondrial",
 
11659
"Brackets or parenthesis [] ()",
 
11660
"ending with period or comma",
 
11661
"ortholog",
 
11662
"orthologue",
 
11663
"paralog",
 
11664
"paralogue",
 
11665
"bifunctional",
 
11666
"pseudogene",
 
11667
"frame shift",
 
11668
"protien",
 
11669
"partial",
 
11670
"B.subtilis",
 
11671
"E.coli",
 
11672
"Escherichia",
 
11673
"coli",
 
11674
"Bacillus",
 
11675
"Subtilis",
 
11676
"Staphlococcus",
 
11677
"aureus",
 
11678
"Salmonella",
 
11679
"Streptococcus",
 
11680
"Staphlococcal",
 
11681
"streptococcal",
 
11682
"Helicobacter",
 
11683
"pylori",
 
11684
"Campylobacter",
 
11685
"Jejuni",
 
11686
"Yersinia",
 
11687
"Pestis",
 
11688
"Rhodobacter",
 
11689
"sphaeroides",
 
11690
};
 
11691
 
 
11692
const int num_suspect_product_names = sizeof (suspect_product_names) / sizeof (CharPtr);
 
11693
 
 
11694
const int brackets_name = 17;
 
11695
const int end_with_punct_name = 18;
 
11696
 
 
11697
 
 
11698
static void FindSuspectProductNamesCallback (SeqFeatPtr sfp, Pointer userdata)
 
11699
{
 
11700
  ValNodePtr PNTR feature_list;
 
11701
  Int4            k, len;
 
11702
  ProtRefPtr      prp;
 
11703
  ValNodePtr      vnp;
 
11704
  CharPtr         str;
 
11705
  
 
11706
  if (sfp == NULL || sfp->data.choice != SEQFEAT_PROT || sfp->data.value.ptrvalue == NULL
 
11707
      || userdata == NULL)
 
11708
  {
 
11709
    return;
 
11710
  }
 
11711
  
 
11712
  prp = (ProtRefPtr) sfp->data.value.ptrvalue;
 
11713
  feature_list = (ValNodePtr PNTR) userdata;
 
11714
  
 
11715
  for (k = 0; k < num_suspect_product_names; k++)
 
11716
  {
 
11717
    if (k == brackets_name)
 
11718
    {
 
11719
      for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
 
11720
      {
 
11721
        if (StringChr (vnp->data.ptrvalue, '[') != NULL
 
11722
            || StringChr (vnp->data.ptrvalue, ']') != NULL
 
11723
            || StringChr (vnp->data.ptrvalue, '(') != NULL
 
11724
            || StringChr (vnp->data.ptrvalue, ')') != NULL)
 
11725
        {
 
11726
          ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
 
11727
          break;
 
11728
        }
 
11729
      }
 
11730
    }
 
11731
    else if (k == end_with_punct_name)
 
11732
    {
 
11733
      for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
 
11734
      {
 
11735
        len = StringLen (vnp->data.ptrvalue);
 
11736
        str = (CharPtr) vnp->data.ptrvalue;
 
11737
        if (str[len - 1] == '.' || str[len - 1] == ',')
 
11738
        {
 
11739
          ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
 
11740
          break;
 
11741
        }
 
11742
      }
 
11743
    }
 
11744
    else
 
11745
    {
 
11746
      if (StringLen (suspect_product_names [k]) < 4)
 
11747
      {
 
11748
        for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
 
11749
        {
 
11750
          if (StringSearch(vnp->data.ptrvalue, suspect_product_names[k]) != NULL)
 
11751
          {
 
11752
            ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
 
11753
            break;
 
11754
          }
 
11755
        }
 
11756
      }
 
11757
      else
 
11758
      {
 
11759
        for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
 
11760
        {
 
11761
          if (StringISearch(vnp->data.ptrvalue, suspect_product_names[k]) != NULL)
 
11762
          {
 
11763
            ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
 
11764
            break;
 
11765
          }
 
11766
        }
 
11767
      }
 
11768
    }
 
11769
  }
 
11770
  
 
11771
}
 
11772
 
 
11773
 
 
11774
static DiscrepancyItemPtr SuspectProductName (CharPtr product_name, ValNodePtr feature_list)
 
11775
{
 
11776
  DiscrepancyItemPtr dip = NULL;
 
11777
  CharPtr            bad_fmt = "%d product names contain %s";
 
11778
 
 
11779
  if (feature_list == NULL || StringHasNoText (product_name))
 
11780
  {
 
11781
    return NULL;
 
11782
  }
 
11783
  
 
11784
  dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
11785
  if (dip != NULL)
 
11786
  {
 
11787
    dip->disc_type = DISC_SUSPECT_PRODUCT_NAME;
 
11788
    dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + StringLen (product_name) + 15));
 
11789
    sprintf (dip->description, bad_fmt, ValNodeLen (feature_list), product_name);
 
11790
    dip->callback_func = NULL;
 
11791
    dip->datafree_func = NULL;
 
11792
    dip->callback_data = NULL;
 
11793
    dip->item_list = feature_list;
 
11794
  }      
 
11795
  return dip;
 
11796
}
 
11797
 
 
11798
 
 
11799
static void FindSuspectProductNames (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
11800
{
 
11801
  ValNodePtr PNTR   feature_list = NULL;
 
11802
  ValNodePtr         master_list = NULL;
 
11803
  Int4               k;
 
11804
  DiscrepancyItemPtr dip;
 
11805
  ValNodePtr         subcategories = NULL;
 
11806
  
 
11807
  if (discrepancy_list == NULL) return;
 
11808
 
 
11809
  feature_list = (ValNodePtr PNTR) MemNew (sizeof (ValNodePtr) * num_suspect_product_names);
 
11810
  if (feature_list == NULL) return;
 
11811
  
 
11812
  /* initialize array for suspicious product names */
 
11813
  for (k = 0; k < num_suspect_product_names; k++)
 
11814
  {
 
11815
    feature_list[k] = NULL;
 
11816
  }
 
11817
  
 
11818
  VisitFeaturesInSep (sep, feature_list, FindSuspectProductNamesCallback);
 
11819
  
 
11820
  for (k = 0; k < num_suspect_product_names; k++)
 
11821
  {
 
11822
    if (feature_list[k] != NULL)
 
11823
    {
 
11824
      dip = SuspectProductName (suspect_product_names[k], feature_list[k]);
 
11825
      if (dip != NULL)
 
11826
      {
 
11827
        ValNodeAddPointer (&subcategories, 0, dip);
 
11828
      }
 
11829
      ValNodeLinkCopy (&master_list, feature_list[k]);
 
11830
    }
 
11831
  }
 
11832
  
 
11833
  if (master_list != NULL)
 
11834
  {
 
11835
    dip = SuspectProductName ("suspect phrase or characters", master_list);
 
11836
    if (dip != NULL)
 
11837
    {
 
11838
      dip->subcategories = subcategories;
 
11839
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
11840
    }
 
11841
  }
 
11842
 
 
11843
  MemFree (feature_list);
 
11844
}
 
11845
 
 
11846
 
 
11847
static DiscrepancyItemPtr InconsistentSourceDefline (SeqDescrPtr biop_sdp, SeqDescrPtr title_sdp)
 
11848
{
 
11849
  DiscrepancyItemPtr dip = NULL;
 
11850
  CharPtr            bad_fmt = "Organism description not found in definition line: %s.";
 
11851
  BioSourcePtr       biop;
 
11852
  CharPtr            desc = NULL;
 
11853
 
 
11854
  if (biop_sdp == NULL || title_sdp == NULL)
 
11855
  {
 
11856
    return NULL;
 
11857
  }
 
11858
  
 
11859
  biop = (BioSourcePtr) biop_sdp->data.ptrvalue;
 
11860
  if (biop != NULL && biop->org != NULL && !StringHasNoText (biop->org->taxname))
 
11861
  {
 
11862
    desc = biop->org->taxname;
 
11863
  }
 
11864
  else
 
11865
  {
 
11866
    desc = title_sdp->data.ptrvalue;
 
11867
  }
 
11868
  if (StringHasNoText (desc)) {
 
11869
    return NULL;
 
11870
  }
 
11871
  
 
11872
  dip = (DiscrepancyItemPtr) MemNew (sizeof (DiscrepancyItemData));
 
11873
  if (dip != NULL)
 
11874
  {
 
11875
    dip->disc_type = DISC_INCONSISTENT_BIOSRC_DEFLINE;
 
11876
    dip->description = (CharPtr)MemNew (StringLen (bad_fmt) + StringLen (desc));
 
11877
    sprintf (dip->description, bad_fmt, desc);
 
11878
    dip->callback_func = NULL;
 
11879
    dip->datafree_func = NULL;
 
11880
    dip->callback_data = NULL;
 
11881
    dip->item_list = NULL;
 
11882
    ValNodeAddPointer (&(dip->item_list), OBJ_SEQDESC, biop_sdp);
 
11883
    ValNodeAddPointer (&(dip->item_list), OBJ_SEQDESC, title_sdp);
 
11884
  }      
 
11885
  return dip;
 
11886
}
 
11887
 
 
11888
 
 
11889
static void FindInconsistentSourceAndDeflineCallback (BioseqPtr bsp, Pointer userdata)
 
11890
{
 
11891
  DiscrepancyItemPtr dip;
 
11892
  ValNodePtr PNTR discrepancy_list;
 
11893
  SeqDescrPtr        biop_sdp, title_sdp;
 
11894
  SeqMgrDescContext  context;
 
11895
  BioSourcePtr       biop;
 
11896
  
 
11897
  discrepancy_list = (ValNodePtr PNTR) userdata;
 
11898
  if (bsp == NULL || discrepancy_list == NULL) return;
 
11899
  
 
11900
  biop_sdp = SeqMgrGetNextDescriptor(bsp, NULL, Seq_descr_source, &context);
 
11901
  if (biop_sdp == NULL || biop_sdp->data.ptrvalue == NULL)
 
11902
  {
 
11903
    return;
 
11904
  }
 
11905
  biop = (BioSourcePtr) biop_sdp->data.ptrvalue;
 
11906
  if (biop->org == NULL)
 
11907
  {
 
11908
    return;
 
11909
  }
 
11910
  if (StringHasNoText (biop->org->taxname)) 
 
11911
  {
 
11912
    return;
 
11913
  }
 
11914
  
 
11915
  title_sdp = SeqMgrGetNextDescriptor(bsp, NULL, Seq_descr_title, &context);
 
11916
  if (title_sdp == NULL) return;
 
11917
  
 
11918
  if (StringStr (title_sdp->data.ptrvalue, biop->org->taxname) == NULL)
 
11919
  {
 
11920
    dip = InconsistentSourceDefline (biop_sdp, title_sdp);
 
11921
    if (dip != NULL)
 
11922
    {
 
11923
      ValNodeAddPointer (discrepancy_list, 0, dip);
 
11924
    }
 
11925
  }
 
11926
}
 
11927
 
 
11928
 
 
11929
static void FindInconsistentSourceAndDefline (SeqEntryPtr sep, ValNodePtr PNTR discrepancy_list)
 
11930
{  
 
11931
  ValNodePtr disc_pairs = NULL;
 
11932
  CharPtr    bad_fmt = "%d sources do not match definition lines.";
 
11933
  DiscrepancyItemPtr dip;
 
11934
  
 
11935
  if (discrepancy_list == NULL) return;
 
11936
 
 
11937
  VisitBioseqsInSep (sep, &disc_pairs, FindInconsistentSourceAndDeflineCallback);
 
11938
 
 
11939
  if (disc_pairs == NULL) 
 
11940
  {
 
11941
    return;
 
11942
  }
 
11943
  else if (disc_pairs->next == NULL)
 
11944
  {
 
11945
    ValNodeLink (discrepancy_list, disc_pairs);
 
11946
  }
 
11947
  else
 
11948
  {
 
11949
    dip = NewDiscrepancyItem (DISC_INCONSISTENT_BIOSRC_DEFLINE, bad_fmt, disc_pairs);
 
11950
    dip->item_list = NULL;
 
11951
    dip->subcategories = disc_pairs;
 
11952
    
 
11953
    ValNodeAddPointer (discrepancy_list, 0, dip);
 
11954
  }
 
11955
}
 
11956
 
 
11957
 
 
11958
static void SetDiscrepancyLevels (ValNodePtr discrepancy_list, Int4 level)
 
11959
{
 
11960
  DiscrepancyItemPtr dip;
 
11961
  
 
11962
  while (discrepancy_list != NULL)
 
11963
  {
 
11964
    dip = (DiscrepancyItemPtr) discrepancy_list->data.ptrvalue;
 
11965
    if (dip != NULL)
 
11966
    {
 
11967
      dip->level = level;
 
11968
      SetDiscrepancyLevels (dip->subcategories, level + 1);
 
11969
    }
 
11970
    discrepancy_list = discrepancy_list->next;
 
11971
  }
 
11972
}
 
11973
 
 
11974
 
 
11975
/* Note that this function contains a hack - it assumes that all of the
 
11976
 * test types that use the same collection function are listed together.
 
11977
 */
 
11978
static ValNodePtr CollectDiscrepancies (SeqEntryPtr sep, DiscrepancyConfigPtr dcp)
 
11979
{
 
11980
  ValNodePtr             discrepancy_list = NULL;
 
11981
  Int4                   i;
 
11982
  PerformDiscrepancyTest last_test_func = NULL;
 
11983
 
 
11984
  for (i = 0; i < MAX_DISC_TYPE; i++)
 
11985
  {
 
11986
    if ((dcp == NULL || dcp->conf_list[i])
 
11987
        && discrepancy_info_list[i].test_func != NULL
 
11988
        && discrepancy_info_list[i].test_func != last_test_func)
 
11989
    {
 
11990
      discrepancy_info_list[i].test_func (sep, &discrepancy_list);
 
11991
      last_test_func = discrepancy_info_list[i].test_func;
 
11992
    }
 
11993
  }
 
11994
  
 
11995
  /* because some tests are run together, need to remove unwanted results */
 
11996
  RemoveUnwantedDiscrepancyItems (&discrepancy_list, dcp);
 
11997
 
 
11998
  /* normalize the discrepancy levels so that they will be correctly displayed */
 
11999
  SetDiscrepancyLevels (discrepancy_list, 0);
 
12000
  return discrepancy_list;  
 
12001
}
 
12002
 
 
12003
static Nlm_ParData discParFmt = {FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
 
12004
static Nlm_ColData discColFmt[2] = {{16, 0, 0, 0, NULL, 'l', 0,0,0,0, FALSE},
 
12005
                                    {1000, 0, 0, 0, NULL, 'l', 1,0,0,0, TRUE}};
 
12006
 
 
12007
 
 
12008
static Int4 CountChosenDiscrepancies (ValNodePtr discrepancy_list, Boolean count_all)
 
12009
{
 
12010
  Int4               num_chosen = 0;
 
12011
  DiscrepancyItemPtr dip;
 
12012
  
 
12013
  while (discrepancy_list != NULL)
 
12014
  {
 
12015
    dip = (DiscrepancyItemPtr) discrepancy_list->data.ptrvalue;
 
12016
    if (dip != NULL)
 
12017
    {
 
12018
      if (dip->chosen || count_all)
 
12019
      {
 
12020
        if (dip->expanded)
 
12021
        {
 
12022
          num_chosen += CountChosenDiscrepancies (dip->subcategories, TRUE);
 
12023
        }
 
12024
        else
 
12025
        {
 
12026
          num_chosen ++;
 
12027
        }
 
12028
      }
 
12029
      else if (dip->expanded)
 
12030
      {
 
12031
        num_chosen += CountChosenDiscrepancies (dip->subcategories, FALSE);
 
12032
      }
 
12033
    }
 
12034
    discrepancy_list = discrepancy_list->next;
 
12035
  }
 
12036
  return num_chosen;
 
12037
}
 
12038
 
 
12039
static Int4 CountLevels (ValNodePtr discrepancy_list)
 
12040
{
 
12041
  Int4       num_levels = 1, num, num_sublevels = 0;
 
12042
  ValNodePtr vnp;
 
12043
  DiscrepancyItemPtr dip;
 
12044
  
 
12045
  if (discrepancy_list == NULL) 
 
12046
  {
 
12047
    return 0;
 
12048
  }
 
12049
  
 
12050
  for (vnp = discrepancy_list; vnp != NULL; vnp = vnp->next)
 
12051
  {
 
12052
    dip = (DiscrepancyItemPtr) vnp->data.ptrvalue;
 
12053
    if (dip == NULL || dip->subcategories == NULL || !dip->expanded)
 
12054
    {
 
12055
      continue;
 
12056
    }
 
12057
    num = CountLevels (dip->subcategories);
 
12058
    if (num > num_sublevels) num_sublevels = num;
 
12059
  }
 
12060
  
 
12061
  /* one level for the top plus levels for the subcategories */
 
12062
 
 
12063
  return 1 + num_sublevels;
 
12064
}
 
12065
 
 
12066
 
 
12067
static Nlm_ColPtr PNTR GetColumnFormatArrays (Int4 num_levels, DoC doc)
 
12068
{
 
12069
  Int4               n, k;
 
12070
  Nlm_ColPtr PNTR    col_fmt_array_array = NULL;
 
12071
  RecT               r;
 
12072
  Int4               doc_width;
 
12073
    
 
12074
  if (num_levels == 0)
 
12075
  {
 
12076
    return NULL;
 
12077
  }
 
12078
  
 
12079
  ObjectRect (doc, &r);
 
12080
  InsetRect (&r, 4, 4);
 
12081
  doc_width = r.right - r.left;
 
12082
  
 
12083
  col_fmt_array_array = (Nlm_ColPtr PNTR) MemNew (sizeof (Nlm_ColPtr) * num_levels);
 
12084
  for (n = 0; n < num_levels; n++)
 
12085
  {
 
12086
    col_fmt_array_array[n] = (Nlm_ColPtr) MemNew (sizeof (Nlm_ColData) * (n + 3));
 
12087
    for (k = 0; k < n + 2; k++)
 
12088
    {
 
12089
      col_fmt_array_array[n][k].pixWidth = 16;
 
12090
      col_fmt_array_array[n][k].pixInset = 0;
 
12091
      col_fmt_array_array[n][k].charWidth = 0;
 
12092
      col_fmt_array_array[n][k].charInset = 0;
 
12093
      col_fmt_array_array[n][k].font = NULL;
 
12094
      col_fmt_array_array[n][k].just = 'l';
 
12095
      col_fmt_array_array[n][k].wrap = 0;
 
12096
      col_fmt_array_array[n][k].bar = 0;
 
12097
      col_fmt_array_array[n][k].underline = 0;
 
12098
      col_fmt_array_array[n][k].left = 0;
 
12099
      col_fmt_array_array[n][k].last = 0;
 
12100
    }
 
12101
    col_fmt_array_array[n][k].pixWidth = doc_width - ((n + 2) * 16);
 
12102
    col_fmt_array_array[n][k].pixInset = 0;
 
12103
    col_fmt_array_array[n][k].charWidth = 0;
 
12104
    col_fmt_array_array[n][k].charInset = 0;
 
12105
    col_fmt_array_array[n][k].font = NULL;
 
12106
    col_fmt_array_array[n][k].just = 'l';
 
12107
    col_fmt_array_array[n][k].wrap = 1;
 
12108
    col_fmt_array_array[n][k].bar = 0;
 
12109
    col_fmt_array_array[n][k].underline = 0;
 
12110
    col_fmt_array_array[n][k].left = 0;
 
12111
    col_fmt_array_array[n][k].last = 1;
 
12112
  }
 
12113
  return col_fmt_array_array;
 
12114
}
 
12115
 
 
12116
 
 
12117
static Nlm_ColPtr PNTR FreeColumnFormatArrays (Nlm_ColPtr PNTR col_fmt_array_array, Int4 num_levels)
 
12118
{
 
12119
  Int4 n;
 
12120
  
 
12121
  if (col_fmt_array_array == NULL || num_levels < 1)
 
12122
  {
 
12123
    return NULL;
 
12124
  }
 
12125
  for (n = 0; n < num_levels; n++)
 
12126
  {
 
12127
    col_fmt_array_array [n] = MemFree (col_fmt_array_array [n]);
 
12128
  }
 
12129
  col_fmt_array_array = MemFree (col_fmt_array_array);
 
12130
  return col_fmt_array_array;
 
12131
}
 
12132
 
 
12133
static void AddDiscrepancyItem (DiscrepancyReportFormPtr drfp, DiscrepancyItemPtr dip, Int4 level)
 
12134
{
 
12135
  CharPtr            item_text;
 
12136
  ValNodePtr         vnp;
 
12137
  Int4               n;
 
12138
 
 
12139
  if (dip == NULL)
 
12140
  {
 
12141
    return;
 
12142
  }
 
12143
  item_text = (CharPtr) MemNew (sizeof (Char) * (StringLen (dip->description) + 6 + level));
 
12144
  for (n = 0; n < level; n++)
 
12145
  {
 
12146
    StringCat (item_text, "\t");
 
12147
  }
 
12148
  StringCat (item_text, " \t \t");
 
12149
  StringCat (item_text, dip->description);
 
12150
  StringCat (item_text, "\n");
 
12151
  AppendText (drfp->doc, item_text, &discParFmt, drfp->col_fmt_array_array [level], programFont);
 
12152
  if (dip->expanded)
 
12153
  {
 
12154
    for (vnp = dip->subcategories; vnp != NULL; vnp = vnp->next)
 
12155
    {
 
12156
      AddDiscrepancyItem (drfp, vnp->data.ptrvalue, level + 1);
 
12157
    }
 
12158
  }
 
12159
}
 
12160
 
 
12161
 
 
12162
static void PopulateDiscrepancyList (DiscrepancyReportFormPtr drfp, ValNodePtr discrepancy_list)
 
12163
{
 
12164
  Int2               numItems;
 
12165
  Int4               num_levels;
 
12166
  
 
12167
  if (drfp == NULL || drfp->doc == NULL) 
 
12168
  {
 
12169
    return;
 
12170
  }
 
12171
  
 
12172
  Reset (drfp->doc);
 
12173
  
 
12174
  num_levels = CountLevels (drfp->discrepancy_list);
 
12175
  if (num_levels != drfp->num_levels)
 
12176
  {
 
12177
    drfp->col_fmt_array_array = FreeColumnFormatArrays (drfp->col_fmt_array_array, drfp->num_levels);
 
12178
    drfp->num_levels = num_levels;
 
12179
    drfp->col_fmt_array_array = GetColumnFormatArrays (drfp->num_levels, drfp->doc);
 
12180
  }
 
12181
  
 
12182
  while (discrepancy_list != NULL)
 
12183
  {
 
12184
    AddDiscrepancyItem (drfp, discrepancy_list->data.ptrvalue, 0);
 
12185
    discrepancy_list = discrepancy_list->next;
 
12186
  }
 
12187
  GetDocParams (drfp->doc, &numItems, NULL);
 
12188
  UpdateDocument (drfp->doc, 0, numItems);
 
12189
 
 
12190
}
 
12191
 
 
12192
static Nlm_ParData discItemParFmt = {FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
 
12193
static Nlm_ColData discItemColFmt [3] = {{0, 5, 10, 0, NULL, 'l', 1,0,0,0, FALSE},
 
12194
                                         {0, 0, 10, 0, NULL, 'l', 1,0,0,0, FALSE},
 
12195
                                         {0, 0, 10, 0, NULL, 'l', 1,0,0,0, TRUE}};
 
12196
 
 
12197
 
 
12198
static CharPtr GetDiscrepancyItemText (ValNodePtr vnp)
 
12199
{
 
12200
  CharPtr           row_text = NULL;
 
12201
  SeqFeatPtr        sfp;
 
12202
  BioseqPtr         bsp;
 
12203
  SeqMgrFeatContext context;
 
12204
  CharPtr           location;
 
12205
  CharPtr           label;
 
12206
  SeqDescrPtr       sdp;
 
12207
  
 
12208
  if (vnp == NULL)
 
12209
  {
 
12210
    return NULL;
 
12211
  }
 
12212
  if (vnp->choice == OBJ_SEQFEAT)
 
12213
  {
 
12214
    sfp = (SeqFeatPtr) vnp->data.ptrvalue;
 
12215
    if (sfp != NULL)
 
12216
    {
 
12217
      sfp = SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL, 0, 0, sfp, &context);
 
12218
      if (sfp != NULL)
 
12219
      {
 
12220
        location = SeqLocPrintUseBestID (sfp->location);
 
12221
        label = (CharPtr) FeatDefTypeLabel(sfp);
 
12222
        row_text = (CharPtr) MemNew (sizeof (Char) * 
 
12223
                                     (StringLen (label) 
 
12224
                                      + StringLen (context.label) 
 
12225
                                      + StringLen (location) 
 
12226
                                      + 4));
 
12227
        sprintf (row_text, "%s\t%s\t%s\n", label, context.label, location);
 
12228
        location = MemFree (location);
 
12229
      }
 
12230
    }
 
12231
  }
 
12232
  else if (vnp->choice == OBJ_BIOSEQ)
 
12233
  {
 
12234
    bsp = (BioseqPtr) vnp->data.ptrvalue;
 
12235
    if (bsp != NULL)
 
12236
    {
 
12237
      row_text = (CharPtr) MemNew (sizeof (Char) * 41);
 
12238
      SeqIdWrite (bsp->id, row_text, PRINTID_REPORT, 39);
 
12239
      StringCat (row_text, "\n");
 
12240
    }
 
12241
  }
 
12242
  else if (vnp->choice == OBJ_SEQDESC)
 
12243
  {
 
12244
    sdp = (SeqDescrPtr) vnp->data.ptrvalue;
 
12245
    if (sdp != NULL)
 
12246
    {
 
12247
      row_text = (CharPtr) MemNew (sizeof (Char) * 61);
 
12248
      SeqDescLabel (sdp, row_text, 59, TRUE);
 
12249
      StringCat (row_text, "\n");
 
12250
    }
 
12251
  }
 
12252
  
 
12253
    
 
12254
  return row_text;
 
12255
}
 
12256
 
 
12257
static void PopulateDiscrepancyItemList (DoC doc, DiscrepancyItemPtr dip)
 
12258
{
 
12259
  ValNodePtr        vnp;
 
12260
  Int2              numItems;
 
12261
  CharPtr           row_text;
 
12262
  RecT              r;
 
12263
  
 
12264
  if (doc == NULL)
 
12265
  {
 
12266
    return;
 
12267
  }
 
12268
  Reset (doc);
 
12269
  
 
12270
  if (dip == NULL)
 
12271
  {
 
12272
    return;
 
12273
  }
 
12274
  
 
12275
  if (dip->item_list == NULL)
 
12276
  {
 
12277
    AppendText (doc, "No items listed", NULL, NULL, programFont);
 
12278
  }
 
12279
  
 
12280
  ObjectRect (doc, &r);
 
12281
  InsetRect (&r, 4, 4);
 
12282
  
 
12283
  discItemColFmt[0].pixWidth = 5 * stdCharWidth;
 
12284
  discItemColFmt[1].pixWidth = (r.right - r.left - discItemColFmt[0].pixWidth) / 2;
 
12285
  discItemColFmt[2].pixWidth = (r.right - r.left - discItemColFmt[0].pixWidth) / 2;
 
12286
  
 
12287
  vnp = dip->item_list;
 
12288
  
 
12289
  while (vnp != NULL)
 
12290
  {
 
12291
    row_text = GetDiscrepancyItemText (vnp);
 
12292
    if (row_text != NULL)
 
12293
    {
 
12294
      if (vnp->choice == OBJ_SEQFEAT)
 
12295
      {
 
12296
        AppendText (doc, row_text, &discItemParFmt, discItemColFmt, programFont);
 
12297
      }
 
12298
      else
 
12299
      {
 
12300
        AppendText (doc, row_text, &discItemParFmt, NULL, programFont);
 
12301
      }
 
12302
      row_text = MemFree (row_text);
 
12303
    }
 
12304
    vnp = vnp->next;
 
12305
  }
 
12306
  GetDocParams (doc, &numItems, NULL);
 
12307
  UpdateDocument (doc, 0, numItems);  
 
12308
}
 
12309
 
 
12310
static DiscrepancyItemPtr GetSubDiscrepancy (ValNodePtr discrepancy_list, Int2Ptr pitem)
 
12311
{
 
12312
  DiscrepancyItemPtr dip = NULL;
 
12313
 
 
12314
  if (discrepancy_list == NULL || pitem == NULL)
 
12315
  {
 
12316
    return NULL;
 
12317
  }
 
12318
  while (*pitem > 0 && discrepancy_list != NULL)
 
12319
  {
 
12320
    (*pitem)--;
 
12321
    dip = (DiscrepancyItemPtr) discrepancy_list->data.ptrvalue;
 
12322
    if (*pitem > 0)
 
12323
    {
 
12324
      if (dip != NULL && dip->expanded)
 
12325
      {
 
12326
        dip = GetSubDiscrepancy (dip->subcategories, pitem);
 
12327
      }
 
12328
    }
 
12329
    discrepancy_list = discrepancy_list->next;
 
12330
  }
 
12331
  if (*pitem > 0)
 
12332
  {
 
12333
    dip = NULL;
 
12334
  }
 
12335
  return dip;
 
12336
}
 
12337
 
 
12338
static DiscrepancyItemPtr GetSelectedDiscrepancy (ValNodePtr discrepancy_list, Int2 item)
 
12339
{
 
12340
  DiscrepancyItemPtr dip = NULL;
 
12341
  
 
12342
  dip = GetSubDiscrepancy (discrepancy_list, &item);
 
12343
 
 
12344
  return dip;
 
12345
}
 
12346
 
 
12347
 
 
12348
static void ClickDiscrepancy (DoC d, PoinT pt)
 
12349
 
 
12350
{
 
12351
  Int2                      item, numItems;
 
12352
  Int2                      row;
 
12353
  Int2                      col;
 
12354
  DiscrepancyReportFormPtr  drfp;
 
12355
  DiscrepancyItemPtr        dip;
 
12356
 
 
12357
  drfp = GetObjectExtra (d);
 
12358
  if (drfp != NULL) {
 
12359
    MapDocPoint (d, pt, &item, &row, &col, NULL);
 
12360
    if (item > 0 && row > 0 && drfp->clicked == item) {
 
12361
      drfp->dblClick = dblClick;
 
12362
    } else {
 
12363
      drfp->dblClick = FALSE;
 
12364
    }
 
12365
    drfp->clicked = 0;
 
12366
    if (item > 0 && row > 0) {
 
12367
      drfp->clicked = item;
 
12368
    }
 
12369
    if (item > 0 && row > 0 && !dblClick)
 
12370
    {
 
12371
      dip = GetSelectedDiscrepancy (drfp->discrepancy_list, item);
 
12372
      if (dip != NULL)
 
12373
      {
 
12374
        if (col == dip->level + 1)
 
12375
        {
 
12376
          dip->chosen = !dip->chosen;
 
12377
          GetDocParams (d, &numItems, NULL);
 
12378
          UpdateDocument (d, 0, numItems);
 
12379
        }
 
12380
        else if (col == dip->level + 2)
 
12381
        {
 
12382
          dip->expanded = !dip->expanded;
 
12383
          PopulateDiscrepancyList (drfp, drfp->discrepancy_list);
 
12384
        }
 
12385
      }
 
12386
    }
 
12387
  }
 
12388
}
 
12389
 
 
12390
 
 
12391
static void ActOnDiscrepancy (ValNodePtr discrepancy_list, Int2 item)
 
12392
{
 
12393
  DiscrepancyItemPtr dip;
 
12394
  
 
12395
  dip = GetSelectedDiscrepancy (discrepancy_list, item);
 
12396
  if (dip != NULL && dip->callback_func != NULL)
 
12397
  {
 
12398
    (dip->callback_func) (dip->item_list, dip->callback_data);
 
12399
  }
 
12400
}
 
12401
 
 
12402
static void InvalBorder (DoC d, Int2 item)
 
12403
 
 
12404
{
 
12405
  Int2  bottom;
 
12406
  RecT  r;
 
12407
  Int2  top;
 
12408
 
 
12409
  ObjectRect (d, &r);
 
12410
  InsetRect (&r, 4, 4);
 
12411
  if (ItemIsVisible (d, item, &top, &bottom, NULL)) {
 
12412
    r.top = top;
 
12413
    r.bottom = bottom;
 
12414
    r.right = r.left + 4;
 
12415
    InsetRect (&r, -1, -1);
 
12416
    InvalRect (&r);
 
12417
  }
 
12418
}
 
12419
 
 
12420
static void ReleaseDiscrepancy (DoC d, PoinT pt)
 
12421
 
 
12422
{
 
12423
  Int2           item;
 
12424
  Int2           old;
 
12425
  Int2           row;
 
12426
  DiscrepancyReportFormPtr  drfp;
 
12427
 
 
12428
  drfp = GetObjectExtra (d);
 
12429
  if (drfp != NULL) {
 
12430
    ResetClip ();
 
12431
    MapDocPoint (d, pt, &item, &row, NULL, NULL);
 
12432
    if (item > 0 && row > 0) {
 
12433
      if (item == drfp->clicked) {
 
12434
        old = drfp->selected;
 
12435
        drfp->selected = item;
 
12436
        if (old != item) {
 
12437
          if (old == 0) {
 
12438
            UpdateDocument (d, item, item);
 
12439
          } else {
 
12440
            UpdateDocument (d, old, old);
 
12441
            UpdateDocument (d, item, item);
 
12442
          }
 
12443
          Update ();
 
12444
        }
 
12445
      }
 
12446
    } else if (drfp->clicked == 0) {
 
12447
      if (drfp->selected != 0) {
 
12448
        old = drfp->selected;
 
12449
        drfp->selected = 0;
 
12450
        InvalBorder (d, old);
 
12451
      }
 
12452
      Update ();
 
12453
    }
 
12454
    if (drfp->selected > 0 && drfp->dblClick)
 
12455
    {
 
12456
      ActOnDiscrepancy (drfp->discrepancy_list, drfp->selected);
 
12457
    }
 
12458
    else if (drfp->selected > 0)
 
12459
    {
 
12460
      drfp->item_selected = 0;
 
12461
      PopulateDiscrepancyItemList (drfp->item_list, 
 
12462
                                   GetSelectedDiscrepancy (drfp->discrepancy_list,
 
12463
                                                           drfp->selected));
 
12464
      
 
12465
    }
 
12466
  }
 
12467
}
 
12468
 
 
12469
 
 
12470
static void DrawDiscrepancy (DoC d, RectPtr r, Int2 item, Int2 firstLine)
 
12471
 
 
12472
{
 
12473
  DiscrepancyReportFormPtr drfp;
 
12474
  RecT                     rct;
 
12475
  DiscrepancyItemPtr       dip;
 
12476
  Int4                     level_offset;
 
12477
 
 
12478
  drfp = (DiscrepancyReportFormPtr) GetObjectExtra (d);
 
12479
  if (drfp != NULL && r != NULL && item > 0 && firstLine == 0) {
 
12480
    rct = *r;
 
12481
  
 
12482
    dip = GetSelectedDiscrepancy (drfp->discrepancy_list, item);
 
12483
    if (dip != NULL)
 
12484
    {
 
12485
      level_offset = dip->level * 16;
 
12486
      rct.left += level_offset;
 
12487
      rct.right += level_offset;
 
12488
    }
 
12489
  
 
12490
    /* draw selection */
 
12491
    if (item == drfp->selected) {
 
12492
      rct.right = rct.left + 4;
 
12493
      PaintRect (&rct);
 
12494
    }
 
12495
 
 
12496
    /* draw chosen checkboxes */
 
12497
    rct.left += 5;
 
12498
    rct.right = rct.left + 10;
 
12499
    rct.bottom = rct.top + (rct.right - rct.left);
 
12500
    FrameRect (&rct);
 
12501
    
 
12502
    if (dip != NULL && dip->chosen) {
 
12503
      MoveTo (rct.left, rct.top);
 
12504
      LineTo (rct.right - 1, rct.bottom - 1);
 
12505
      MoveTo (rct.left, rct.bottom - 1);
 
12506
      LineTo (rct.right - 1, rct.top);
 
12507
    }
 
12508
    
 
12509
    /* draw open/closed checkboxes */
 
12510
    if (dip!= NULL && dip->subcategories != NULL)
 
12511
    {
 
12512
      rct.left += 10;
 
12513
      rct.right = rct.left + 10;
 
12514
      rct.bottom = rct.top + (rct.right - rct.left);
 
12515
      FrameRect (&rct);
 
12516
      MoveTo (rct.left, (rct.top + rct.bottom) / 2);
 
12517
      LineTo (rct.right - 1, (rct.top + rct.bottom) / 2);
 
12518
      if (!dip->expanded)
 
12519
      {
 
12520
        MoveTo ((rct.left + rct.right) / 2, rct.top);
 
12521
        LineTo ((rct.left + rct.right) / 2, rct.bottom - 1);
 
12522
      }
 
12523
    }
 
12524
  }
 
12525
}
 
12526
 
 
12527
 
 
12528
 
 
12529
static void DrawDiscrepancyItem (DoC d, RectPtr r, Int2 item, Int2 firstLine)
 
12530
 
 
12531
{
 
12532
  DiscrepancyReportFormPtr drfp;
 
12533
  RecT                     rct;
 
12534
 
 
12535
  drfp = (DiscrepancyReportFormPtr) GetObjectExtra (d);
 
12536
  if (drfp != NULL && r != NULL && item > 0 && firstLine == 0) {
 
12537
    rct = *r;
 
12538
  
 
12539
    /* draw selection */
 
12540
    if (item == drfp->item_selected) {
 
12541
      rct = *r;
 
12542
      rct.right = rct.left + 4;
 
12543
      PaintRect (&rct);
 
12544
    }
 
12545
  }
 
12546
}
 
12547
 
 
12548
 
 
12549
static void EditDiscrepancyItem (ValNodePtr vnp)
 
12550
{
 
12551
  SeqFeatPtr sfp;
 
12552
  BioseqPtr  bsp;
 
12553
  SeqDescrPtr sdp;
 
12554
  ObjValNodePtr ovp;
 
12555
  
 
12556
  if (vnp == NULL)
 
12557
  {
 
12558
    return;
 
12559
  }
 
12560
  if (vnp->choice == OBJ_SEQFEAT)
 
12561
  {
 
12562
    sfp = (SeqFeatPtr) vnp->data.ptrvalue;
 
12563
    if (sfp != NULL)
 
12564
    {
 
12565
      GatherProcLaunch (OMPROC_EDIT, FALSE, sfp->idx.entityID, sfp->idx.itemID,
 
12566
                        OBJ_SEQFEAT, 0, 0, OBJ_SEQFEAT, 0);
 
12567
    }
 
12568
  }
 
12569
  else if (vnp->choice == OBJ_BIOSEQ)
 
12570
  {
 
12571
    bsp = (BioseqPtr) vnp->data.ptrvalue;
 
12572
    if (bsp != NULL)
 
12573
    {
 
12574
      GatherProcLaunch (OMPROC_EDIT, FALSE, bsp->idx.entityID, bsp->idx.itemID,
 
12575
                         OBJ_BIOSEQ, 0, 0, OBJ_BIOSEQ, 0);
 
12576
    }
 
12577
  }
 
12578
  else if (vnp->choice == OBJ_SEQDESC)
 
12579
  {
 
12580
    sdp = (SeqDescrPtr) (vnp->data.ptrvalue);
 
12581
    if (sdp != NULL && sdp->extended != 0)
 
12582
    {
 
12583
      ovp = (ObjValNodePtr) sdp;
 
12584
      GatherProcLaunch (OMPROC_EDIT, FALSE, ovp->idx.entityID, ovp->idx.itemID,
 
12585
                         OBJ_SEQDESC, 0, 0, OBJ_SEQDESC, 0);
 
12586
    }
 
12587
  }
 
12588
 
 
12589
}
 
12590
 
 
12591
 
 
12592
static void SetBioseqViewTargetByBioseq (BaseFormPtr bfp, BioseqPtr bsp)
 
12593
{
 
12594
  Char       id_text [41];
 
12595
  
 
12596
  if (bsp != NULL && bfp != NULL)
 
12597
  {
 
12598
    SeqIdWrite (SeqIdFindBest (bsp->id, 0), id_text, PRINTID_REPORT, sizeof (id_text));
 
12599
    SetBioseqViewTarget (bfp, id_text);
 
12600
  }
 
12601
}
 
12602
 
 
12603
 
 
12604
static BioseqPtr GetFirstBioseqInSeqEntry (SeqEntryPtr sep)
 
12605
{
 
12606
  BioseqPtr    bsp = NULL;
 
12607
  BioseqSetPtr bssp;
 
12608
  
 
12609
  if (sep == NULL || sep->data.ptrvalue == NULL)
 
12610
  {
 
12611
    return NULL;
 
12612
  }
 
12613
  else if (IS_Bioseq (sep))
 
12614
  {
 
12615
    bsp = sep->data.ptrvalue;
 
12616
  }
 
12617
  else if (IS_Bioseq_set (sep))
 
12618
  {
 
12619
    bssp = (BioseqSetPtr) sep->data.ptrvalue;
 
12620
    for (sep = bssp->seq_set; sep != NULL && bsp == NULL; sep = sep->next)
 
12621
    {
 
12622
      bsp = GetFirstBioseqInSeqEntry (sep);
 
12623
    }
 
12624
  }
 
12625
  return bsp;
 
12626
}
 
12627
 
 
12628
 
 
12629
static BioseqPtr GetBioseqForDescriptor (ObjValNodePtr ovp)
 
12630
{
 
12631
  BioseqPtr    bsp = NULL;
 
12632
  BioseqSetPtr bssp;
 
12633
  SeqEntryPtr  sep;
 
12634
  
 
12635
  if (ovp == NULL || ovp->idx.parentptr == NULL)
 
12636
  {
 
12637
    return NULL;
 
12638
  }
 
12639
  else if (ovp->idx.parenttype == OBJ_BIOSEQ) {
 
12640
    bsp = (BioseqPtr) ovp->idx.parentptr;
 
12641
  } else if (ovp->idx.parenttype == OBJ_BIOSEQSET) {
 
12642
    bssp = (BioseqSetPtr) ovp->idx.parentptr;
 
12643
    for (sep = bssp->seq_set; sep != NULL && bsp == NULL; sep = sep->next)
 
12644
    {
 
12645
      bsp = GetFirstBioseqInSeqEntry (sep);
 
12646
    }  
 
12647
  }
 
12648
  return bsp;
 
12649
}
 
12650
 
 
12651
static void ScrollToDiscrepancyItem (ValNodePtr vnp, BaseFormPtr bfp)
 
12652
{
 
12653
  SeqFeatPtr    sfp;
 
12654
  BioseqPtr     bsp;
 
12655
  SeqDescrPtr   sdp;
 
12656
  ObjValNodePtr ovp;
 
12657
  
 
12658
  if (vnp == NULL || bfp == NULL)
 
12659
  {
 
12660
    return;
 
12661
  }
 
12662
  if (vnp->choice == OBJ_SEQFEAT)
 
12663
  {
 
12664
    sfp = (SeqFeatPtr) vnp->data.ptrvalue;
 
12665
    if (sfp != NULL)
 
12666
    {
 
12667
      /* need to scroll to item */
 
12668
      bsp = BioseqFindFromSeqLoc (sfp->location);
 
12669
      SetBioseqViewTargetByBioseq (bfp, bsp);
 
12670
      ObjMgrSelect (sfp->idx.entityID, sfp->idx.itemID, OBJ_SEQFEAT, 0, NULL);
 
12671
    }
 
12672
  }
 
12673
  else if (vnp->choice == OBJ_BIOSEQ)
 
12674
  {
 
12675
    bsp = (BioseqPtr) vnp->data.ptrvalue;
 
12676
    SetBioseqViewTargetByBioseq (bfp, bsp);
 
12677
  }
 
12678
  else if (vnp->choice == OBJ_SEQDESC)
 
12679
  {
 
12680
    sdp = (SeqDescrPtr) (vnp->data.ptrvalue);
 
12681
    if (sdp != NULL && sdp->extended != 0)
 
12682
    {
 
12683
      ovp = (ObjValNodePtr) sdp;      
 
12684
      bsp = GetBioseqForDescriptor (ovp);
 
12685
      SetBioseqViewTargetByBioseq (bfp, bsp);
 
12686
      ObjMgrSelect (ovp->idx.entityID, ovp->idx.itemID, OBJ_SEQDESC, 0, NULL);
 
12687
    }
 
12688
  }
 
12689
}
 
12690
 
 
12691
static void ClickDiscrepancyItem (DoC d, PoinT pt)
 
12692
 
 
12693
{
 
12694
  Int2                      item, last_selected, numItems;
 
12695
  Int2                      row;
 
12696
  DiscrepancyReportFormPtr  drfp;
 
12697
  DiscrepancyItemPtr        dip;
 
12698
  ValNodePtr                vnp;
 
12699
 
 
12700
  drfp = GetObjectExtra (d);
 
12701
  if (drfp != NULL) {
 
12702
    MapDocPoint (d, pt, &item, &row, NULL, NULL);
 
12703
    if (item > 0 && row > 0) {  
 
12704
      dip = GetSelectedDiscrepancy (drfp->discrepancy_list, drfp->selected);
 
12705
      if (dip != NULL && dip->item_list != NULL)
 
12706
      {
 
12707
        vnp = dip->item_list;
 
12708
        
 
12709
        last_selected = drfp->item_selected;
 
12710
        drfp->item_selected = item;
 
12711
        
 
12712
        if (item != last_selected)
 
12713
        {
 
12714
          GetDocParams (d, &numItems, NULL);
 
12715
          UpdateDocument (d, 0, numItems);
 
12716
        }
 
12717
    
 
12718
        /* find item in list */
 
12719
        while (item > 1 && vnp != NULL)
 
12720
        {
 
12721
          vnp = vnp->next;
 
12722
          item--;
 
12723
        }
 
12724
        
 
12725
        if (dblClick)
 
12726
        {
 
12727
          EditDiscrepancyItem (vnp);
 
12728
        }
 
12729
        else
 
12730
        {
 
12731
          ScrollToDiscrepancyItem (vnp, drfp->bfp);
 
12732
        } 
 
12733
         
 
12734
      }
 
12735
    }
 
12736
  }
 
12737
}
 
12738
 
 
12739
 
 
12740
static void CleanupDiscrepancyReportForm (GraphiC g, VoidPtr data)
 
12741
 
 
12742
{
 
12743
  DiscrepancyReportFormPtr drfp;
 
12744
 
 
12745
  drfp = (DiscrepancyReportFormPtr) data;
 
12746
  if (drfp != NULL) {
 
12747
    drfp->discrepancy_list = FreeDiscrepancyList (drfp->discrepancy_list);
 
12748
    drfp->dcp = DiscrepancyConfigFree (drfp->dcp);
 
12749
    drfp->col_fmt_array_array = FreeColumnFormatArrays (drfp->col_fmt_array_array, drfp->num_levels);
 
12750
    ObjMgrFreeUserData (drfp->input_entityID, drfp->procid, drfp->proctype, drfp->userkey);
 
12751
    discrepancyReportWindow = NULL;
 
12752
  }
 
12753
  StdCleanupFormProc (g, data);
 
12754
}
 
12755
 
 
12756
static void RecheckDiscrepancyProc (ButtoN b)
 
12757
{
 
12758
  DiscrepancyReportFormPtr drfp;
 
12759
 
 
12760
  drfp = (DiscrepancyReportFormPtr) GetObjectExtra (b);
 
12761
  if (drfp != NULL)
 
12762
  {
 
12763
    drfp->discrepancy_list = FreeDiscrepancyList (drfp->discrepancy_list);
 
12764
    drfp->discrepancy_list = CollectDiscrepancies (drfp->sep, drfp->dcp);
 
12765
    PopulateDiscrepancyList (drfp, drfp->discrepancy_list);
 
12766
    if (drfp->discrepancy_list != NULL)
 
12767
    {
 
12768
      drfp->selected = 1;
 
12769
      drfp->item_selected = 0;
 
12770
      PopulateDiscrepancyItemList (drfp->item_list, 
 
12771
                                   GetSelectedDiscrepancy (drfp->discrepancy_list,
 
12772
                                                           drfp->selected));
 
12773
    }
 
12774
    else
 
12775
    {
 
12776
      Reset (drfp->item_list);
 
12777
    }
 
12778
  }
 
12779
}
 
12780
 
 
12781
 
 
12782
static ValNodePtr ValNodePointerDup (ValNodePtr vnp)
 
12783
{
 
12784
  ValNodePtr vnp_new = NULL;
 
12785
  
 
12786
  if (vnp != NULL)
 
12787
  {
 
12788
    vnp_new = ValNodeNew (NULL);
 
12789
    vnp_new->choice = vnp->choice;
 
12790
    vnp_new->data.ptrvalue = vnp->data.ptrvalue;
 
12791
    vnp_new->next = ValNodePointerDup (vnp->next);
 
12792
  }
 
12793
  return vnp_new;
 
12794
}
 
12795
 
 
12796
static ValNodePtr ReplaceDiscrepancyItemWithFeatureTableStrings (ValNodePtr feat_list)
 
12797
{
 
12798
  BioseqPtr       bsp;
 
12799
  CstType         custom_flags = 0;
 
12800
  Asn2gbJobPtr    ajp;
 
12801
  BaseBlockPtr    bbp;
 
12802
  Int4            index;
 
12803
  SeqFeatPtr      sfp;
 
12804
  ValNodePtr      vnp, list_copy = NULL, list_vnp;
 
12805
  
 
12806
  if (feat_list == NULL) return NULL;
 
12807
  
 
12808
  list_copy = ValNodePointerDup (feat_list);
 
12809
  for (vnp = list_copy; vnp != NULL; vnp = vnp->next)
 
12810
  {
 
12811
    if (vnp->choice == OBJ_SEQFEAT)
 
12812
    {
 
12813
      sfp = (SeqFeatPtr) vnp->data.ptrvalue;
 
12814
      bsp = BioseqFindFromSeqLoc (sfp->location);
 
12815
      ajp = asn2gnbk_setup (bsp, NULL, NULL, FTABLE_FMT, DUMP_MODE, NORMAL_STYLE,
 
12816
                             0, 0, custom_flags, NULL);
 
12817
      if (ajp != NULL)
 
12818
      {
 
12819
        for (index = 0; index < ajp->numParagraphs; index++) 
 
12820
        {
 
12821
          bbp = ajp->paragraphArray [index];
 
12822
          for (list_vnp = vnp; list_vnp != NULL; list_vnp = list_vnp->next)
 
12823
          {
 
12824
            if (list_vnp->choice == OBJ_SEQFEAT)
 
12825
            {
 
12826
              sfp = (SeqFeatPtr) list_vnp->data.ptrvalue;
 
12827
              if (sfp != NULL 
 
12828
                  && bbp->entityID == sfp->idx.entityID
 
12829
                  && bbp->itemtype == sfp->idx.itemtype
 
12830
                  && bbp->itemID == sfp->idx.itemID)
 
12831
              {
 
12832
                /* replace list feature with description, change choice */
 
12833
                list_vnp->choice = 0;
 
12834
                list_vnp->data.ptrvalue = asn2gnbk_format (ajp, (Int4) index);
 
12835
              }
 
12836
            }
 
12837
          }
 
12838
        }
 
12839
        asn2gnbk_cleanup (ajp);
 
12840
      }
 
12841
    }
 
12842
  }
 
12843
  return list_copy;
 
12844
}
 
12845
 
 
12846
 
 
12847
static void WriteDiscrepancy (FILE *fp, DiscrepancyItemPtr dip, Boolean use_feature_table_fmt)
 
12848
{
 
12849
  ValNodePtr vnp, list_copy = NULL;
 
12850
  CharPtr    row_text;
 
12851
  
 
12852
  if (fp == NULL || dip == NULL)
 
12853
  {
 
12854
    return;
 
12855
  }
 
12856
  
 
12857
  fprintf (fp, "%s\n", dip->description);
 
12858
  vnp = dip->item_list;
 
12859
  
 
12860
  if (use_feature_table_fmt)
 
12861
  {
 
12862
    list_copy = ReplaceDiscrepancyItemWithFeatureTableStrings (vnp);
 
12863
    vnp = list_copy;
 
12864
  }
 
12865
 
 
12866
  while (vnp != NULL)
 
12867
  {
 
12868
    if (vnp->choice == 0 && use_feature_table_fmt)
 
12869
    {
 
12870
      row_text = vnp->data.ptrvalue;
 
12871
    }
 
12872
    else
 
12873
    {
 
12874
      row_text = GetDiscrepancyItemText (vnp);
 
12875
    }
 
12876
    if (row_text != NULL)
 
12877
    {
 
12878
      fprintf (fp, row_text);
 
12879
      row_text = MemFree (row_text);
 
12880
    }
 
12881
    vnp = vnp->next;
 
12882
  }
 
12883
  
 
12884
  fprintf (fp, "\n");
 
12885
}
 
12886
 
 
12887
static void 
 
12888
WriteDiscrepancyReport 
 
12889
(FILE       *fp,
 
12890
 ValNodePtr discrepancy_list, 
 
12891
 Boolean    show_all,
 
12892
 Boolean    use_feature_table_fmt)
 
12893
{
 
12894
  DiscrepancyItemPtr       dip;
 
12895
  ValNodePtr               vnp;
 
12896
  Int4                     num_chosen;
 
12897
 
 
12898
  if (fp == NULL || discrepancy_list == NULL)
 
12899
  {
 
12900
    return;
 
12901
  }
 
12902
  for (vnp = discrepancy_list; vnp != NULL; vnp = vnp->next)
 
12903
  {
 
12904
    dip = (DiscrepancyItemPtr) vnp->data.ptrvalue;
 
12905
    if (dip != NULL)
 
12906
    {
 
12907
      if (dip->expanded)
 
12908
      {
 
12909
        num_chosen = CountChosenDiscrepancies (dip->subcategories, show_all | dip->chosen);
 
12910
        if (num_chosen > 0)
 
12911
        {
 
12912
          if (dip->chosen || show_all)
 
12913
          {
 
12914
            fprintf (fp, "%s\n", dip->description);
 
12915
          }
 
12916
          WriteDiscrepancyReport (fp, dip->subcategories, show_all | dip->chosen, use_feature_table_fmt);          
 
12917
        }
 
12918
      }
 
12919
      else if (dip->chosen || show_all)
 
12920
      {
 
12921
        WriteDiscrepancy (fp, dip, use_feature_table_fmt);
 
12922
      }
 
12923
    }
 
12924
  }
 
12925
}
 
12926
 
 
12927
static Boolean DiscrepancyReportExportProc (ForM f, CharPtr filename)
 
12928
 
 
12929
{
 
12930
  FILE           *fp;
 
12931
  Char           path [PATH_MAX];
 
12932
  DiscrepancyReportFormPtr drfp;
 
12933
  Int4                     num_disc = 0;
 
12934
  Boolean                  show_all = FALSE;
 
12935
 
 
12936
  drfp = (DiscrepancyReportFormPtr) GetObjectExtra (f);
 
12937
  if (drfp == NULL) 
 
12938
  {
 
12939
    return FALSE;
 
12940
  }
 
12941
  
 
12942
  num_disc = CountChosenDiscrepancies (drfp->discrepancy_list, FALSE);
 
12943
 
 
12944
  if (num_disc == 0) 
 
12945
  {
 
12946
    if (ANS_CANCEL == Message (MSG_OKC, "No discrepancies selected!  Export all?"))
 
12947
    {
 
12948
      return FALSE;
 
12949
    }
 
12950
    else
 
12951
    {
 
12952
      show_all = TRUE;
 
12953
    }
 
12954
  }
 
12955
  
 
12956
  path [0] = '\0';
 
12957
  StringNCpy_0 (path, filename, sizeof (path));
 
12958
  if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
 
12959
#ifdef WIN_MAC
 
12960
    fp = FileOpen (path, "r");
 
12961
    if (fp != NULL) {
 
12962
      FileClose (fp);
 
12963
    } else {
 
12964
      FileCreate (path, "TEXT", "ttxt");
 
12965
    }
 
12966
#endif
 
12967
    fp = FileOpen (path, "w");
 
12968
    if (fp != NULL) {
 
12969
      WriteDiscrepancyReport (fp, drfp->discrepancy_list, show_all, 
 
12970
                              (Boolean)(drfp->dcp != NULL && drfp->dcp->use_feature_table_format));
 
12971
      FileClose (fp);
 
12972
      return TRUE;
 
12973
    }
 
12974
  }
 
12975
  return FALSE;
 
12976
}
 
12977
 
 
12978
 
 
12979
static void GenerateDiscrepancyReport (ButtoN b)
 
12980
{
 
12981
  DiscrepancyReportFormPtr drfp;
 
12982
  Char                     path [PATH_MAX];
 
12983
 
 
12984
  drfp = (DiscrepancyReportFormPtr) GetObjectExtra (b);
 
12985
  if (drfp == NULL)
 
12986
  {
 
12987
    return;
 
12988
  }
 
12989
 
 
12990
  TmpNam (path);  
 
12991
  if (DiscrepancyReportExportProc (drfp->form, path))
 
12992
  {
 
12993
    LaunchGeneralTextViewer (path, "Discrepancy Report");
 
12994
  }
 
12995
  FileRemove (path);  
 
12996
}
 
12997
 
 
12998
 
 
12999
static void CopyDiscrepancyReportToClipboard (DiscrepancyReportFormPtr drfp)
 
13000
 
 
13001
{
 
13002
  FILE         *fp;
 
13003
  Char         path [PATH_MAX];
 
13004
 
 
13005
  if (drfp == NULL || drfp->discrepancy_list == NULL) return;
 
13006
  TmpNam (path);
 
13007
  fp = FileOpen (path, "w");
 
13008
  if (fp != NULL) {
 
13009
    WriteDiscrepancyReport (fp, drfp->discrepancy_list, TRUE, 
 
13010
                            (Boolean)(drfp->dcp != NULL && drfp->dcp->use_feature_table_format));
 
13011
    FileClose (fp);
 
13012
    FileToClipboard (path);
 
13013
  }
 
13014
  FileRemove (path);
 
13015
}
 
13016
 
 
13017
 
 
13018
static void DiscrepancyReportFormMessage (ForM f, Int2 mssg)
 
13019
 
 
13020
{
 
13021
  DiscrepancyReportFormPtr drfp;
 
13022
 
 
13023
  drfp = (DiscrepancyReportFormPtr) GetObjectExtra (f);
 
13024
  if (drfp != NULL) {
 
13025
    switch (mssg) {
 
13026
      case VIB_MSG_EXPORT :
 
13027
        DiscrepancyReportExportProc (f, NULL);
 
13028
        break;
 
13029
      case VIB_MSG_PRINT :
 
13030
        break;
 
13031
      case VIB_MSG_CLOSE :
 
13032
        Remove (f);
 
13033
        break;
 
13034
      case VIB_MSG_CUT :
 
13035
        CopyDiscrepancyReportToClipboard (drfp);
 
13036
        break;
 
13037
      case VIB_MSG_COPY :
 
13038
        CopyDiscrepancyReportToClipboard (drfp);
 
13039
        break;
 
13040
      case VIB_MSG_PASTE :
 
13041
        break;
 
13042
      case VIB_MSG_DELETE :
 
13043
        drfp->discrepancy_list = ValNodeFree (drfp->discrepancy_list);
 
13044
        Reset (drfp->doc);
 
13045
        Reset (drfp->item_list);
 
13046
        break;
 
13047
      default :
 
13048
        if (drfp->appmessage != NULL) {
 
13049
          drfp->appmessage (f, mssg);
 
13050
        }
 
13051
        break;
 
13052
    }
 
13053
  }
 
13054
}
 
13055
 
 
13056
 
 
13057
static void ReactivateDiscrepancyReport (BaseFormPtr bfp)
 
13058
{
 
13059
  DiscrepancyReportFormPtr drfp;
 
13060
 
 
13061
  if (discrepancyReportWindow == NULL) 
 
13062
  {
 
13063
    CreateDiscrepancyReportWindow (bfp);
 
13064
  }
 
13065
  
 
13066
  drfp = (DiscrepancyReportFormPtr) GetObjectExtra (discrepancyReportWindow);
 
13067
  if (drfp == NULL)
 
13068
  {
 
13069
    Remove (discrepancyReportWindow);
 
13070
    discrepancyReportWindow = NULL;
 
13071
    CreateDiscrepancyReportWindow (bfp);
 
13072
  }
 
13073
  
 
13074
  drfp->bfp = bfp;
 
13075
  drfp->input_entityID = bfp->input_entityID;
 
13076
  drfp->sep = GetTopSeqEntryForEntityID (drfp->input_entityID);
 
13077
  
 
13078
  /* populate discrepancy lists */
 
13079
  RecheckDiscrepancyProc (drfp->recheck_btn);
 
13080
  Show (discrepancyReportWindow);  
 
13081
}
 
13082
 
 
13083
 
 
13084
static void EditDiscrepancyConfigBtn (ButtoN b)
 
13085
{
 
13086
  DiscrepancyReportFormPtr drfp;
 
13087
  
 
13088
  drfp = (DiscrepancyReportFormPtr) GetObjectExtra (discrepancyReportWindow);
 
13089
  if (drfp == NULL) return;
 
13090
  
 
13091
  if (EditDiscrepancyConfig (drfp->dcp))
 
13092
  {
 
13093
    RecheckDiscrepancyProc (b);
 
13094
  }
 
13095
}
 
13096
 
 
13097
 
 
13098
#ifndef WIN_MAC
 
13099
extern void CreateStdValidatorFormMenus (WindoW w);
 
13100
#endif
 
13101
 
 
13102
 
 
13103
static Int2 LIBCALLBACK DiscrepancyReportMsgFunc (OMMsgStructPtr ommsp)
 
13104
{
 
13105
  WindoW                   currentport,
 
13106
                           temport;
 
13107
  OMUserDataPtr            omudp;
 
13108
  DiscrepancyReportFormPtr drfp = NULL;
 
13109
  
 
13110
  omudp = (OMUserDataPtr)(ommsp->omuserdata);
 
13111
  if (omudp == NULL) return OM_MSG_RET_ERROR;
 
13112
  drfp = (DiscrepancyReportFormPtr) omudp->userdata.ptrvalue;
 
13113
  if (drfp == NULL) return OM_MSG_RET_ERROR;
 
13114
 
 
13115
  currentport = ParentWindow (drfp->form);
 
13116
  temport = SavePort (currentport);
 
13117
  UseWindow (currentport);
 
13118
  Select (drfp->form);
 
13119
  switch (ommsp->message) 
 
13120
  {
 
13121
      case OM_MSG_UPDATE:
 
13122
          break;
 
13123
      case OM_MSG_DESELECT:
 
13124
          break;
 
13125
 
 
13126
      case OM_MSG_SELECT: 
 
13127
          break;
 
13128
      case OM_MSG_DEL:
 
13129
          Remove (drfp->form);
 
13130
          break;
 
13131
      case OM_MSG_HIDE:
 
13132
          break;
 
13133
      case OM_MSG_SHOW:
 
13134
          break;
 
13135
      case OM_MSG_FLUSH:
 
13136
          Remove (drfp->form);  
 
13137
          break;
 
13138
      default:
 
13139
          break;
 
13140
  }
 
13141
  RestorePort (temport);
 
13142
  UseWindow (temport);
 
13143
  return OM_MSG_RET_OK;
 
13144
}
 
13145
 
 
13146
 
 
13147
extern void CreateDiscrepancyReportWindow (BaseFormPtr bfp)
 
13148
{
 
13149
  DiscrepancyReportFormPtr drfp;
 
13150
  GrouP                    h, g;
 
13151
  ButtoN                   b;
 
13152
  GrouP                    c;
 
13153
  RecT                     r;
 
13154
  WindoW                   w;
 
13155
  OMUserDataPtr            omudp;
 
13156
 
 
13157
  if (bfp == NULL) return;
 
13158
  
 
13159
  if (discrepancyReportWindow != NULL)
 
13160
  {
 
13161
    ReactivateDiscrepancyReport (bfp);
 
13162
    return; 
 
13163
  }
 
13164
  
 
13165
  drfp = (DiscrepancyReportFormPtr) MemNew (sizeof (DiscrepancyReportFormData));
 
13166
  if (drfp == NULL)
 
13167
  {
 
13168
    return;
 
13169
  }
 
13170
  
 
13171
  drfp->bfp = bfp;
 
13172
  drfp->input_entityID = bfp->input_entityID;
 
13173
  drfp->sep = GetTopSeqEntryForEntityID (drfp->input_entityID);
 
13174
  w = FixedWindow (-50, -33, -10, -10, "Discrepancy Report", StdCloseWindowProc);
 
13175
  SetObjectExtra (w, drfp, CleanupDiscrepancyReportForm);
 
13176
  drfp->form = (ForM) w;
 
13177
  drfp->formmessage = DiscrepancyReportFormMessage;
 
13178
  drfp->exportform = DiscrepancyReportExportProc;
 
13179
  
 
13180
  /* read in config file */
 
13181
  drfp->dcp = ReadDiscrepancyConfig();
 
13182
  
 
13183
  /* register to receive update messages */
 
13184
  drfp->userkey = OMGetNextUserKey ();
 
13185
  drfp->procid = 0;
 
13186
  drfp->proctype = OMPROC_EDIT;
 
13187
  omudp = ObjMgrAddUserData (drfp->input_entityID, drfp->procid, drfp->proctype, drfp->userkey);
 
13188
  if (omudp != NULL) {
 
13189
    omudp->userdata.ptrvalue = (Pointer) drfp;
 
13190
    omudp->messagefunc = DiscrepancyReportMsgFunc;
 
13191
  }
 
13192
 
 
13193
 
 
13194
#ifndef WIN_MAC
 
13195
  CreateStdValidatorFormMenus (w);
 
13196
#endif
 
13197
 
 
13198
  h = HiddenGroup (w, -1, 0, NULL);
 
13199
  SetGroupSpacing (h, 10, 10);
 
13200
  
 
13201
  g = HiddenGroup (h, 2, 0, NULL);
 
13202
  StaticPrompt (g, "Discrepancies", 0, popupMenuHeight, programFont, 'c');
 
13203
  StaticPrompt (g, "Affected Items", 0, popupMenuHeight, programFont, 'c');
 
13204
  
 
13205
  drfp->doc = DocumentPanel (g, stdCharWidth * 30, stdLineHeight * 20);
 
13206
  SetObjectExtra (drfp->doc, drfp, NULL);
 
13207
  SetDocAutoAdjust (drfp->doc, FALSE);
 
13208
  SetDocProcs (drfp->doc, ClickDiscrepancy, NULL, ReleaseDiscrepancy, NULL);
 
13209
  SetDocShade (drfp->doc, DrawDiscrepancy, NULL, NULL, NULL);
 
13210
  
 
13211
  drfp->item_list = DocumentPanel (g, stdCharWidth * 30 + 5, stdLineHeight * 20);
 
13212
  SetObjectExtra (drfp->item_list, drfp, NULL);
 
13213
  SetDocAutoAdjust (drfp->item_list, FALSE);
 
13214
  SetDocProcs (drfp->item_list, ClickDiscrepancyItem, NULL, NULL, NULL);
 
13215
  SetDocShade (drfp->item_list, DrawDiscrepancyItem, NULL, NULL, NULL);
 
13216
 
 
13217
  c = HiddenGroup (h, 4, 0, NULL);
 
13218
  SetGroupSpacing (c, 10, 10);
 
13219
  b = PushButton (c, "Generate Report", GenerateDiscrepancyReport);
 
13220
  SetObjectExtra (b, drfp, NULL);
 
13221
  drfp->recheck_btn = PushButton (c, "Recheck", RecheckDiscrepancyProc);
 
13222
  SetObjectExtra (drfp->recheck_btn, drfp, NULL);
 
13223
  
 
13224
  b = PushButton (c, "Configure", EditDiscrepancyConfigBtn);
 
13225
  SetObjectExtra (b, drfp, NULL);
 
13226
  
 
13227
  PushButton (c, "Dismiss", StdCancelButtonProc);
 
13228
 
 
13229
  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
 
13230
 
 
13231
  RealizeWindow (w);
 
13232
  
 
13233
  /* adjust column width for discrepancy list */
 
13234
  ObjectRect (drfp->doc, &r);
 
13235
  InsetRect (&r, 4, 4);
 
13236
  discColFmt[1].pixWidth = r.right - r.left - discColFmt[0].pixWidth;
 
13237
 
 
13238
  /* populate discrepancy lists */
 
13239
  RecheckDiscrepancyProc (drfp->recheck_btn);
 
13240
  Show (w);
 
13241
  discrepancyReportWindow = w;
 
13242
}
 
13243