void PoissonSubstitutionProcess::AddMeanSuffStat(double*** down, double*** up, double*** at, double branchlength, double* meanratecount, double* meanratebeta, double& meanlengthcount, double& meanlengthbeta, double** meanprofilecount, int* nonmissing, double* weight)   {

    for (int i=GetSiteMin(); i<GetSiteMax(); i++)   {
        if (ActiveSite(i))  {
            double extw = 1.0;
            if (weight) {
                extw = weight[i];
            }
            if (nonmissing[i] == 2)    {
                
                if (branchlength)   {
                    cerr << "error: non root for missing 2\n";
                    exit(1);
                }

                int nstate = GetNstate(i);
                int j = ratealloc[i];

                double* a = at[i][j];
                double totz[nstate];
                double tot = 0;
                for (int k=0; k<nstate; k++)    {
                    totz[k] = a[k];
                    tot += totz[k];
                }
                for (int k=0; k<nstate; k++)    {
                    totz[k] /= tot;
                }
                AddZipToTrueMeanProfileSuffStat(i,totz,meanprofilecount[i],extw);

            }
            else if (nonmissing[i] == 1)  {

                if (! down) {
                    cerr << "error in PoissonSubstitutionProcess::AddMeanSuffStat: non root calculation called on root\n";
                    exit(1);
                }

                if (! branchlength) {
                    cerr << "error: root for missing 1\n";
                    exit(1);
                }

                int nstate = GetNstate(i);
                const double* stat = GetStationary(i);
                double rate = GetRate(i);
                double length = rate * branchlength;
                double e = exp(-length);

                int j = ratealloc[i];
                double* d = down[i][j];
                double* u = up[i][j];

                double totw = 0;
                double totn = 0;
                double totz[nstate];
                for (int k=0; k<nstate; k++)    {
                    totz[k] = 0;
                }

                double hidden = 0;
                for (int k=0; k<nstate; k++)    {
                    for (int l=0; l<nstate; l++)    {
                        if (k == l) {
                            double w = stat[k] * d[k] * u[l] * (e + (1-e)*stat[l]);
                            totw += w;
                            double n = length * stat[k] / (e + (1-e)*stat[k]);
                            double z = (1-e) * stat[k] / (e + (1-e)*stat[k]);
                            totn += w * n;
                            totz[l] += w * z;
                            hidden += w * (n-z);
                        }
                        else    {
                            double w = stat[k] * d[k] * u[l] * (1-e) * stat[l];
                            totw += w;
                            double n = 0;
                            if (length < 1e-8)  {
                                n = 1;
                            }
                            else    {
                                n = length / (1-e);
                            }
                            double z = 1;
                            totn += w * n;
                            totz[l] += w * z;
                            hidden += w * (n-z);
                        }
                    }
                }
                if (totw)   {
                    totn /= totw;
                }
                else    {
                    totn = 0;
                }
                if (isnan(totn))    {
                    cerr << "totn is nan\n";
                    cerr << totw << '\n';
                    exit(1);
                }
                double total = 0;
                for (int k=0; k<nstate; k++)    {
                    totz[k] += hidden * stat[k];
                    if (totw)   {
                        totz[k] /= totw;
                    }
                    else    {
                        totz[k] = 0;
                    }
                    total += totz[k];
                }
                if (fabs(total - totn) > 1e-6)  {
                    cerr << "error in total count in PoissonSubstitutionProcess::AddMeanSuffStat\n";
                    exit(1);
                }

                AddZipToTrueMeanProfileSuffStat(i,totz,meanprofilecount[i],extw);

                meanratecount[i] += extw * totn;
                meanratebeta[i] += extw * branchlength;
                meanlengthcount += extw * totn;
                meanlengthbeta += extw * rate;
            }
        }
    }
}
STDMETHODIMP CStreamSwitcherPassThru::GetRate(double* pdRate)
{
	CallPeerSeeking(GetRate(pdRate));
}
void TranscriptionToolBar::OnAutomateSelection(wxCommandEvent & WXUNUSED(event))
{


   //If IO is busy, abort immediately
   if (gAudioIO->IsBusy())
   {
      SetButton(false,mButtons[TTB_EndOff]);
      return;
   }

   wxBusyCursor busy;

   mVk->AdjustThreshold(GetSensitivity());
   AudacityProject *p = GetActiveProject();
   TrackList *tl = p->GetTracks();
   TrackListOfKindIterator iter(Track::Wave, tl);

   Track *t = iter.First();   //Make a track
   if(t)
      {
         auto wt = static_cast<const WaveTrack*>(t);
         sampleCount start, len;
         GetSamples(wt, &start, &len);

         //Adjust length to end if selection is null
         if(len == 0)
            {
               len = start;
               start = 0;
            }
         sampleCount lastlen = 0;
         double newStartPos, newEndPos;


         //This is the minumum word size in samples (.05 is 50 ms)
         int minWordSize = (int)(wt->GetRate() * .05);

         //Continue until we have processed the entire
         //region, or we are making no progress.
         while(len > 0 && lastlen != len)
            {

               lastlen = len;

               auto newStart = mVk->OnForward(*wt, start, len);

               //JKC: If no start found then don't add any labels.
               if( newStart==start)
                  break;

               //Adjust len by the NEW start position
               len -= (newStart - start);

               //Adjust len by the minimum word size
               len -= minWordSize;



               //OK, now we have found a NEW starting point.  A 'word' should be at least
               //50 ms long, so jump ahead minWordSize

               auto newEnd   =
                  mVk->OffForward(*wt, newStart + minWordSize, len);

               //If newEnd didn't move, we should give up, because
               // there isn't another end before the end of the selection.
               if(newEnd == (newStart + minWordSize))
                  break;


               //Adjust len by the NEW word end
               len -= (newEnd - newStart);

               //Calculate the start and end of the words, in seconds
               newStartPos = newStart.as_double() / wt->GetRate();
               newEndPos = newEnd.as_double() / wt->GetRate();


               //Increment
               start = newEnd;

               p->DoAddLabel(SelectedRegion(newStartPos, newEndPos));
               p->RedrawProject();
            }
         SetButton(false, mButtons[TTB_AutomateSelection]);
      }
}