bool  CSeqAnnotFromFasta::BuildMasterSlaveSeqAlign(const CRef<CSeq_id>& masterSeqid, const CRef<CSeq_id>& slaveSeqid, const string& masterSequence, const string& slaveSequence, const vector<unsigned int>& blockStarts, const vector<unsigned int>& blockLengths, CRef<CSeq_align>& pairwiseSA) 
{
    typedef CSeq_align::C_Segs::TDendiag TDD;

    map<unsigned int, unsigned int> nGapsPriorToBlockStart, nGapsPriorToBlockStartMaster;
    unsigned int j, masterStart, slaveStart;
    unsigned int nBlocks = blockStarts.size();

    if (masterSequence.length() == 0 || slaveSequence.length() == 0) return false;
    if (masterSeqid.Empty() || slaveSeqid.Empty()) return false;
    if (nBlocks != blockLengths.size()) return false;

    CountNonAlphaToPositions(blockStarts, masterSequence, nGapsPriorToBlockStartMaster);
    CountNonAlphaToPositions(blockStarts, slaveSequence, nGapsPriorToBlockStart);

    if (pairwiseSA.Empty()) {
        pairwiseSA.Reset(new CSeq_align());
        if (pairwiseSA.Empty()) {
            return false;
        }
    }

    pairwiseSA->SetType(CSeq_align::eType_partial);
    pairwiseSA->SetDim(2);
        
    TDD& ddl = pairwiseSA->SetSegs().SetDendiag();
    for (j = 0; j < nBlocks; ++j) {

        CRef< CDense_diag > dd(new CDense_diag());
        dd->SetDim(2);

        //  Fill in the Seq-ids.
        CRef< CSeq_id > masterCopy = CopySeqId(masterSeqid);
        CRef< CSeq_id > slaveCopy = CopySeqId(slaveSeqid);
        CDense_diag::TIds& ids = dd->SetIds();
        ids.push_back(masterCopy);
        ids.push_back(slaveCopy);

        //  Fill in the block starts & length
        masterStart = blockStarts[j] - nGapsPriorToBlockStartMaster[blockStarts[j]];
        slaveStart  = blockStarts[j] - nGapsPriorToBlockStart[blockStarts[j]];
        dd->SetStarts().push_back(masterStart);
        dd->SetStarts().push_back(slaveStart);
        dd->SetLen(blockLengths[j]);

        //cerr << "seq " << i+1 << " block " << j+1 << endl;
//            cerr << "    blockStarts[j] = " << blockStarts[j] << "; nGaps-master = " << nGapsPriorToBlockStartMaster[blockStarts[j]] << ", nGaps-slave = " << nGapsPriorToBlockStart[blockStarts[j]] << endl;
        //cerr << "    master Start " << masterStart << "; slave Start " << slaveStart << endl;

        ddl.push_back(dd);
    }

    return true;
}
// Check p-values and compare with the referece file
void s_CheckPValues(const CRef<CScorePValues> pv, const string& filename)
{
    BOOST_REQUIRE(!pv.Empty());

    const vector<CScorePValues::TPValue>& pvalues = pv->GetPValues();
    const vector<CScorePValues::TPValue>& errors = pv->GetErrors();

    // P-values and errors arrays are of the same length
    BOOST_REQUIRE_EQUAL(pvalues.size(), errors.size());

    // P-values and errors are positive
    for (size_t i=0;i < pvalues.size();i++) {
        BOOST_REQUIRE(pvalues[i] >= 0.0);
        BOOST_REQUIRE(errors[i] >= 0.0);
    }

    // Compare p-values and error to the reference values
    CNcbiIfstream istr_pv(filename.c_str());
    BOOST_REQUIRE(istr_pv.is_open());
    for (size_t j=0;j < pvalues.size();j++) {

        double target;

        BOOST_REQUIRE(!istr_pv.eof());
        
        istr_pv >> target;
        BOOST_REQUIRE_CLOSE(pvalues[j], target, 1.0);

        istr_pv >> target;
        BOOST_REQUIRE_CLOSE(errors[j], target, 1.0);
    }
}
static CRef<CGumbelParamsResult>
s_CalcGumbelParams(CRef<CGumbelParamsOptions> opts, double time,
                   CRef<CGumbelParamsRandDiagnostics> params =
                   CRef<CGumbelParamsRandDiagnostics>())
{
    double mult = NCBI_GetCheckTimeoutMult();
    opts->SetMaxCalcTime(time * mult);
    BOOST_REQUIRE(opts->Validate());
    CRef<CGumbelParamsCalc> calc;
    if (params.Empty()) {
        calc.Reset(new CGumbelParamsCalc(opts));
    }
    else {
        calc.Reset(new CGumbelParamsCalc(opts, params));
    }

    try {
        calc->Run();
    }
    catch (CGumbelParamsException& e) {
        if (e.GetErrCode() == CGumbelParamsException::eLimitsExceeded) {
            BOOST_REQUIRE_MESSAGE(false, (string)"Time out with threshold "
                                  + NStr::DoubleToString(time) + "s and "
                                  "multiplier " + NStr::DoubleToString(mult));
        }
    }

    return calc->GetResult();
}
Esempio n. 4
0
static CProt_ref::EECNumberFileStatus s_LoadECNumberTable(const string& dir, const string& name,
                                const char* const *fallback,
                                size_t fallback_count,
                                CProt_ref::EECNumberStatus status)
{
    CRef<ILineReader> lr;
    CProt_ref::EECNumberFileStatus rval = CProt_ref::eECFile_not_attempted;

    if ( !dir.empty() ) {
        lr.Reset(ILineReader::New
                 (CDirEntry::MakePath(dir, "ecnum_" + name, "txt")));
        rval = CProt_ref::eECFile_not_found;
    }
    if (lr.Empty()) {
        while (fallback_count--) {
            s_ProcessECNumberLine(*fallback++, status);
        }
    } else {
        rval = CProt_ref::eECFile_not_read;
        do {
            s_ProcessECNumberLine(*++*lr, status);
            rval = CProt_ref::eECFile_read;
        } while ( !lr->AtEOF() );
    }
    return rval;
}
Esempio n. 5
0
 /// Returns true if its argument's frame corresponds to the one used to
 /// create this object
 /// @param seqlocinfo the object to examine [in]
 bool operator() (const CRef<CSeqLocInfo>& seqlocinfo) const {
     if (seqlocinfo.Empty()) {
         NCBI_THROW(CBlastException, eInvalidArgument, 
                    "Empty CRef<CSeqLocInfo>!");
     }
     return (seqlocinfo->GetFrame() == m_Frame) ? true : false;
 }
void CExportStrategy::x_Process_SearchDb(CRef<CSearchDatabase> & db)
{
    if (db.Empty())
    {
        NCBI_THROW(CBlastException, eInvalidArgument,
                   "Empty reference for CSearchDatabase.");
    }

	if (db->GetDatabaseName().empty())
	{
	    NCBI_THROW(CBlastException, eInvalidArgument,
	               "Error: No database specified");
	}

	// Set database Name
	CRef<CBlast4_subject> subject_p(new CBlast4_subject);
	subject_p->SetDatabase(db->GetDatabaseName());
	m_QueueSearchRequest->SetSubject(*subject_p);

	// Set Entrez Query Limitation
	string entrez_query_limit = db->GetEntrezQueryLimitation();
	if(!entrez_query_limit.empty())
	{
		CRef<CBlast4_parameter> p(new CBlast4_parameter);
		p->SetName(CBlast4Field::GetName(eBlastOpt_EntrezQuery));

		CRef<CBlast4_value> v(new CBlast4_value);
		v->SetString().assign(entrez_query_limit);
		p->SetValue(*v);
		_ASSERT(CBlast4Field::Get(eBlastOpt_EntrezQuery).Match(*p));

		m_QueueSearchRequest->SetProgram_options().Set().push_back(p);
	}

    // Set the GI List Limitation
    const CSearchDatabase::TGiList& gi_list_limit = db->GetGiListLimitation();
    if (!gi_list_limit.empty())
    {
    	x_AddParameterToProgramOptions(CBlast4Field::Get(eBlastOpt_GiList), gi_list_limit);
    }

    // Set the negative GI list
    const CSearchDatabase::TGiList& neg_gi_list = db->GetNegativeGiListLimitation();
    if (!neg_gi_list.empty())
    {
    	x_AddParameterToProgramOptions(CBlast4Field::Get(eBlastOpt_NegativeGiList), neg_gi_list);
    }

    // Set the filtering algorithms
    int algo_id = db->GetFilteringAlgorithm();
    if (algo_id != -1)
    {
       	x_AddParameterToProgramOptions(CBlast4Field::Get(eBlastOpt_DbFilteringAlgorithmId), algo_id);
    }
}
int ReadMsa(const string& filename, CRef<CSeq_align>& align,
            CRef<CScope> scope, bool parse_deflines /* = false*/,
            objects::CSeqIdGenerator* id_generator /* = NULL*/)
{
    if (scope.Empty()) {
        return -1;
    }

    CNcbiIfstream instream(filename.c_str());
    if (!instream) {
        return -1;
    }
    CStreamLineReader line_reader(instream);

    CFastaReader::TFlags flags =  CFastaReader::fAssumeProt |
        CFastaReader::fForceType | CFastaReader::fValidate;
    
    if (!parse_deflines) {
        flags |= CFastaReader::fNoParseID;
    }

    CFastaReader fasta_reader(line_reader, flags);

    if (id_generator) {
        fasta_reader.SetIDGenerator(*id_generator);
    }

    CRef<CSeq_entry> entry = fasta_reader.ReadAlignedSet(-1);
    if (entry.Empty()) {
        return -1;
    }
    scope->AddTopLevelSeqEntry(*entry);

    // notify of a problem if the whole file was not read
    if (!line_reader.AtEOF()) {
        return -1;
    }

    align = entry->GetAnnot().front()->GetData().GetAlign().front();

    return 0;
}
Esempio n. 8
0
    /// Auxiliary function to create a Bioseq given a CSeq_id ready to be added
    /// to a BlastObject, which does NOT contain sequence data
    /// @param id Sequence id for this bioseq [in]
    CRef<CBioseq> x_CreateBioseq(CRef<CSeq_id> id)
    {
        if (m_BioseqMaker.Empty()) {
            m_QueryScopeSource.Reset(new CBlastScopeSource(m_DLConfig));
            m_BioseqMaker.Reset
                (new CBlastBioseqMaker(m_QueryScopeSource->NewScope()));
        }

        x_ValidateMoleculeType(id);
        return m_BioseqMaker->CreateBioseqFromId(id, m_RetrieveSeqData);
    }
static CRef<blast::CExportStrategy>
s_InitializeExportStrategy(CRef<blast::IQueryFactory> queries,
                      	 CRef<blast::CBlastDatabaseArgs> db_args,
                      	 CRef<blast::CBlastOptionsHandle> opts_hndl,
                      	 const string& client_id /* = kEmptyStr */,
                      	 CRef<objects::CPssmWithParameters> pssm
                         /* = CRef<objects::CPssmWithParameters>() */,
                         unsigned int num_iters
                         /* = 0 */)
{
    _ASSERT(queries || pssm);
    _ASSERT(db_args);
    _ASSERT(opts_hndl);

    CRef<CExportStrategy> retval;

    CRef<CSearchDatabase> search_db = db_args->GetSearchDatabase();
    if (search_db.NotEmpty())
    {
        if (pssm.NotEmpty())
        {
            _ASSERT(queries.Empty());
            if(num_iters != 0)
            	retval.Reset(new blast::CExportStrategy(pssm, opts_hndl, search_db, client_id, num_iters));
            else
            	retval.Reset(new blast::CExportStrategy(pssm, opts_hndl, search_db, client_id));
        }
        else
        {
            if(num_iters != 0)
            	retval.Reset(new blast::CExportStrategy(queries, opts_hndl, search_db, client_id, num_iters));
            else
            	retval.Reset(new blast::CExportStrategy(queries, opts_hndl, search_db, client_id));
        }
    }
    else
    {
        if (pssm.NotEmpty())
        {
            NCBI_THROW(CInputException, eInvalidInput,
                       "Remote PSI-BL2SEQ is not supported");
        }
        else
        {
            retval.Reset(new blast::CExportStrategy(queries, opts_hndl,
            								 db_args->GetSubjects(), client_id));
        }
    }

    return retval;
}
Esempio n. 10
0
void
CBlastScopeSource::x_InitBlastDatabaseDataLoader(CRef<CSeqDB> db_handle)
{
    if ( !m_Config.m_UseBlastDbs ) {
        return;
    }

    if (db_handle.Empty()) {
        ERR_POST(Warning << "No BLAST database handle provided");
    } else {
        try {

            m_BlastDbLoaderName = CBlastDbDataLoader::RegisterInObjectManager
                    (*m_ObjMgr, db_handle, m_Config.m_UseFixedSizeSlices,
                     CObjectManager::eNonDefault).GetLoader()->GetName();
            _ASSERT( !m_BlastDbLoaderName.empty() );
            _TRACE("Registered BLAST DB data loader '" << m_BlastDbLoaderName 
                   << "' as non-default");

        } catch (const exception& e) {

            // in case of error when initializing the BLAST database, just
            // ignore the exception as the remote BLAST database data loader
            // will be the fallback (just issue a warning)
            ERR_POST(Warning << "Error initializing local BLAST database data "
                             << "loader: '" << e.what() << "'");
            const CBlastDbDataLoader::EDbType dbtype = 
                db_handle->GetSequenceType() == CSeqDB::eProtein
                ? CBlastDbDataLoader::eProtein
                : CBlastDbDataLoader::eNucleotide;
            try {
                m_BlastDbLoaderName =
                    CRemoteBlastDbDataLoader::RegisterInObjectManager
                        (*m_ObjMgr, db_handle->GetDBNameList(), dbtype,
                         m_Config.m_UseFixedSizeSlices,
                         CObjectManager::eNonDefault,
                         CObjectManager::kPriority_NotSet)
                         .GetLoader()->GetName();
                _ASSERT( !m_BlastDbLoaderName.empty() );
                _TRACE("Registered BLAST DB data loader '" << m_BlastDbLoaderName 
                       << "' as non-default");
            } catch (const CSeqDBException& e) {
                ERR_POST(Warning << "Error initializing remote BLAST database "
                              << "data loader: " << e.GetMsg());
            }
        }
    }
}
Esempio n. 11
0
void CExportStrategy::x_Process_SearchDb(CRef<CSearchDatabase> & db)
{
    if (db.Empty())
    {
        NCBI_THROW(CBlastException, eInvalidArgument,
                   "Empty reference for CSearchDatabase.");
    }

	if (db->GetDatabaseName().empty())
	{
	    NCBI_THROW(CBlastException, eInvalidArgument,
	               "Error: No database specified");
	}

	// Set database Name
	CRef<CBlast4_subject> subject_p(new CBlast4_subject);
	subject_p->SetDatabase(db->GetDatabaseName());
	m_QueueSearchRequest->SetSubject(*subject_p);

	// Set Entrez Query Limitation
	string entrez_query_limit = db->GetEntrezQueryLimitation();
	if(!entrez_query_limit.empty())
	{
		CRef<CBlast4_parameter> p(new CBlast4_parameter);
		p->SetName(CBlast4Field::GetName(eBlastOpt_EntrezQuery));

		CRef<CBlast4_value> v(new CBlast4_value);
		v->SetString().assign(entrez_query_limit);
		p->SetValue(*v);
		_ASSERT(CBlast4Field::Get(eBlastOpt_EntrezQuery).Match(*p));

		m_QueueSearchRequest->SetProgram_options().Set().push_back(p);
	}

    // Set the GI List Limitation
    const CSearchDatabase::TGiList& gi_list_limit = db->GetGiListLimitation();
    if (!gi_list_limit.empty())
    {
		#ifdef NCBI_STRICT_GI
       		vector<int> int_gi_list;
       		ITERATE ( vector<TGi>, it, gi_list_limit ) {
       			int_gi_list.push_back(GI_TO( int, *it));
       		}
CRef<blast::CRemoteBlast> 
InitializeRemoteBlast(CRef<blast::IQueryFactory> queries,
                      CRef<blast::CBlastDatabaseArgs> db_args,
                      CRef<blast::CBlastOptionsHandle> opts_hndl,
                      bool verbose_output,
                      const string& client_id /* = kEmptyStr */,
                      CRef<objects::CPssmWithParameters> pssm 
                        /* = CRef<objects::CPssmWithParameters>() */)
{
    _ASSERT(queries || pssm);
    _ASSERT(db_args);
    _ASSERT(opts_hndl);

    CRef<CRemoteBlast> retval;

    CRef<CSearchDatabase> search_db = db_args->GetSearchDatabase();
    if (search_db.NotEmpty()) {
        if (pssm.NotEmpty()) {
            _ASSERT(queries.Empty());
            retval.Reset(new CRemoteBlast(pssm, opts_hndl, *search_db));
        } else {
            retval.Reset(new CRemoteBlast(queries, opts_hndl, *search_db));
        }
    } else {
        if (pssm.NotEmpty()) {
            NCBI_THROW(CInputException, eInvalidInput,
                       "Remote PSI-BL2SEQ is not supported");
        } else {
            // N.B.: there is NO scope needed in the GetSubjects call because
            // the subjects (if any) should have already been added in 
            // InitializeSubject 
            retval.Reset(new CRemoteBlast(queries, opts_hndl,
                                         db_args->GetSubjects()));
        }
    }
    if (verbose_output) {
        retval->SetVerbose();
    }
    if (client_id != kEmptyStr) {
        retval->SetClientId(client_id);
    }
    return retval;
}
Esempio n. 13
0
static void s_LoadECNumberTable(const string& dir, const string& name,
                                const char* const *fallback,
                                size_t fallback_count,
                                CProt_ref::EECNumberStatus status)
{
    CRef<ILineReader> lr;
    if ( !dir.empty() ) {
        lr.Reset(ILineReader::New
                 (CDirEntry::MakePath(dir, "ecnum_" + name, "txt")));
    }
    if (lr.Empty()) {
        while (fallback_count--) {
            s_ProcessECNumberLine(*fallback++, status);
        }
    } else {
        do {
            s_ProcessECNumberLine(*++*lr, status);
        } while ( !lr->AtEOF() );
    }
}
Esempio n. 14
0
BEGIN_NCBI_SCOPE


CRef<ILineReader> ILineReader::New(const string& filename)
{
    CRef<ILineReader> lr;
    if (filename != "-") {
        try {
            lr.Reset(new CMemoryLineReader(new CMemoryFile(filename),
                                           eTakeOwnership));
        } catch (exception& e) { // CFileException is the main concern
            ERR_POST_X(1, Info << "ILineReader::New: falling back from"
                       " CMemoryLineReader to CBufferedLineReader for "
                       << filename << " due to exception: " << e.what());
        }
    }
    if (lr.Empty()) {
        lr.Reset(new CBufferedLineReader(filename));
    }
    return lr;
}
void CExportStrategy::x_Process_Pssm(CRef<CPssmWithParameters> & pssm)
{
    if (pssm.Empty())
    {
        NCBI_THROW(CBlastException, eInvalidArgument,
                   "Empty reference for query pssm.");
    }

    // Throw exception if pssm is invalid
    CPsiBlastValidate::Pssm(*pssm);

    string psi_program("blastp");
    string old_service("plain");
    string new_service("psi");
    string deltablast("delta_blast");

    if (m_QueueSearchRequest->GetProgram() != psi_program)
    {
        NCBI_THROW(CBlastException, eNotSupported,
                   "PSI-Blast is only supported for blastp.");
    }

    if ((m_QueueSearchRequest->GetService() != old_service) &&
        (m_QueueSearchRequest->GetService() != new_service) &&
        (m_QueueSearchRequest->GetService() != deltablast))
    {
        NCBI_THROW(CBlastException, eInvalidArgument,
                   string("PSI-Blast cannot also be ") +
                   m_QueueSearchRequest->GetService() + ".");
    }

    CRef<CBlast4_queries> queries_p(new CBlast4_queries);
    queries_p->SetPssm(*pssm);

    m_QueueSearchRequest->SetQueries(*queries_p);
    m_QueueSearchRequest->SetService(new_service);
}
void CExportStrategy::x_Process_BlastOptions(CRef<CBlastOptionsHandle>  & opts_handle)
{
    if (opts_handle.Empty())
    {
        NCBI_THROW(CBlastException, eInvalidArgument,
                   "Empty reference for CBlastOptionsHandle.");
    }

    string program;
    string service;
    opts_handle->GetOptions().GetRemoteProgramAndService_Blast3(program, service);

    if (program.empty())
    {
            NCBI_THROW(CBlastException, eInvalidArgument,
                       "NULL argument specified: program");
    }

    if (service.empty())
    {
        NCBI_THROW(CBlastException, eInvalidArgument,
                   "NULL argument specified: service");
    }

    m_QueueSearchRequest->SetProgram(program);
    m_QueueSearchRequest->SetService(service);

    CBlast4_parameters *	algo_opts = opts_handle->SetOptions().GetBlast4AlgoOpts();
    if (NULL == algo_opts )
    {
        NCBI_THROW(CBlastException, eInvalidArgument,
                   "NULL argument specified: algo options");
    }

    m_QueueSearchRequest->SetAlgorithm_options().Set() = *algo_opts;
}
Esempio n. 17
0
 /// Initialize and cache BLAST DB handle if necessary
 void x_InitBlastDb() {
     if (m_BlastDb.Empty()) {
         m_BlastDb = m_DbInitInfo.InitSeqDb();
     }
     _ASSERT(m_BlastDb.NotEmpty());
 }
void
InitializeSubject(CRef<blast::CBlastDatabaseArgs> db_args, 
                  CRef<blast::CBlastOptionsHandle> opts_hndl,
                  bool is_remote_search,
                  CRef<blast::CLocalDbAdapter>& db_adapter, 
                  CRef<objects::CScope>& scope)
{
    db_adapter.Reset();

    _ASSERT(db_args.NotEmpty());
    CRef<CSearchDatabase> search_db = db_args->GetSearchDatabase();

    // Initialize the scope... 
    if (is_remote_search) {
        const bool is_protein = 
            Blast_SubjectIsProtein(opts_hndl->GetOptions().GetProgramType())
			? true : false;
        SDataLoaderConfig config(is_protein);
        if (search_db.NotEmpty() && search_db->GetDatabaseName() != "n/a") {
            config.m_BlastDbName = search_db->GetDatabaseName();
        }
        CBlastScopeSource scope_src(config);
        // configure scope to fetch sequences remotely for formatting
        if (scope.NotEmpty()) {
            scope_src.AddDataLoaders(scope);
        } else {
            scope = scope_src.NewScope();
        }
    } else {
        if (scope.Empty()) {
            scope.Reset(new CScope(*CObjectManager::GetInstance()));
        }
    }
    _ASSERT(scope.NotEmpty());

    // ... and then the subjects
    CRef<IQueryFactory> subjects;
    if ( (subjects = db_args->GetSubjects(scope)) ) {
        _ASSERT(search_db.Empty());
        db_adapter.Reset(new CLocalDbAdapter(subjects, opts_hndl));
    } else {
        _ASSERT(search_db.NotEmpty());
        try { 
            // Try to open the BLAST database even for remote searches, as if
            // it is available locally, it will be better to fetch the
            // sequence data for formatting from this (local) source
            CRef<CSeqDB> seqdb = search_db->GetSeqDb();
            db_adapter.Reset(new CLocalDbAdapter(*search_db));
            scope->AddDataLoader(RegisterOMDataLoader(seqdb));
        } catch (const CSeqDBException&) {
            // The BLAST database couldn't be found, report this for local
            // searches, but for remote searches go on.
            if (is_remote_search ) {
                db_adapter.Reset(new CLocalDbAdapter(*search_db));
            } else {
                throw;
            }
        }
    }

    /// Set the BLASTDB data loader as the default data loader (if applicable)
    if (search_db.NotEmpty()) {
        string dbloader_name =
            s_FindBlastDbDataLoaderName(search_db->GetDatabaseName(),
                                        search_db->IsProtein());
        if ( !dbloader_name.empty() ) {
            // FIXME: will this work with multiple BLAST DBs?
            scope->AddDataLoader(dbloader_name, 
                             CBlastDatabaseArgs::kSubjectsDataLoaderPriority);
            _TRACE("Setting " << dbloader_name << " priority to "
                   << (int)CBlastDatabaseArgs::kSubjectsDataLoaderPriority
                   << " for subjects");
        }
    }
}
Esempio n. 19
0
bool PortalBookURLToCCddBookRef(const string& portalBookUrl, CRef < CCdd_book_ref >& bookRef)
{
    bool result = false;
    if (bookRef.Empty()) return result;

    //  remove leading/trailing whitespace from input url
    string inputStr = NStr::TruncateSpaces(portalBookUrl);

    string baseStr, nbkCode, idStr;
    string typeStr = kEmptyStr;
    CRegexp regexpBase("/books/(NBK.+)");
    CRegexp regexpNBK("^(NBK[^/]+)");
    CRegexp regexpRendertype("^NBK[^/]+/(.+)/(.+)");

    CUrl url(inputStr);
    CUrlArgs& urlArgs = url.GetArgs();
    string urlPath = url.GetPath();
    string urlFrag = url.GetFragment();  //  fragment is text after trailing '#'

    //  remove a trailing '/' in the path (e.g., '.../?report=objectonly' form of URLs)
    if (NStr::EndsWith(urlPath, '/')) { 
        urlPath = urlPath.substr(0, urlPath.length() - 1);
    }

    regexpBase.GetMatch(urlPath, 0, 0, CRegexp::fMatch_default, true);
    if (regexpBase.NumFound() == 2) {  //  i.e., found full pattern + subpattern

        baseStr = regexpBase.GetSub(urlPath, 1);
        nbkCode = regexpNBK.GetMatch(baseStr);

        regexpRendertype.GetMatch(baseStr, 0, 0, CRegexp::fMatch_default, true);        
        if (regexpRendertype.NumFound() == 3) {  //  i.e., full pattern + two subpatterns
            typeStr = regexpRendertype.GetSub(baseStr, 1);
            idStr = regexpRendertype.GetSub(baseStr, 2);
        } else if (urlArgs.IsSetValue("rendertype") && urlArgs.IsSetValue("id")) {
            //  If the user somehow pasted a redirected br.fcgi URL.
            typeStr = urlArgs.GetValue("rendertype");
            idStr = urlArgs.GetValue("id");
        } else if (urlFrag.length() > 0) {
            //  A section id appears after the hash character.
            typeStr = "section";
            idStr = urlFrag;
        } else if (urlFrag.length() == 0) {
            //  If there is no URL fragment or obvious type, designate it 
            //  a chapter and point to the top of this book page.
            typeStr = "chapter";
            idStr = kEmptyStr;
        }
    }

    if (nbkCode.length() > 0) {

        //  'figure' maps to 'eTextelement_figgrp'
        //  'def-item' maps to 'eTextelement_glossary'
        //  if have no type at this point, treat as either a section or chapter
        if (typeStr == "figure")
            typeStr = "figgrp";
        else if (typeStr == "def-item")
            typeStr = "glossary";
//        else if (typeStr.length() == 0) 
//            typeStr = (idStr.length() > 0) ? "section" : "chapter";

        CCdd_book_ref::ETextelement typeEnum;
        const CEnumeratedTypeValues* allowedElements = CCdd_book_ref::GetTypeInfo_enum_ETextelement();
        if (allowedElements && allowedElements->IsValidName(typeStr)) { 
            //  Since 'IsValidName' is true, don't need to catch thrown 
            //  error in the case 'typeStr' is not found.
            typeEnum = (CCdd_book_ref::ETextelement) allowedElements->FindValue(typeStr);
        } else {  
            //  treat invalid typeStr as a 'section' or 'chapter'
            typeEnum  = (idStr.length() > 0) ? CCdd_book_ref::eTextelement_section : CCdd_book_ref::eTextelement_chapter;
        }

        bookRef->SetBookname(nbkCode);
        bookRef->SetTextelement(typeEnum);
        bookRef->SetCelementid(idStr);
        result = true;
    }

    return result;
}
void CExportStrategy::x_Process_Query(CRef<IQueryFactory> & query)
{
    if (query.Empty())
    {
        NCBI_THROW(CBlastException, eInvalidArgument,
                   "Error: No queries specified");
    }

    CRef<IRemoteQueryData> remote_query(query->MakeRemoteQueryData());
    CRef<CBioseq_set> bioseq_set = remote_query->GetBioseqSet();
    IRemoteQueryData::TSeqLocs seqloc_list = remote_query->GetSeqLocs();

    if (bioseq_set.Empty() && seqloc_list.empty())
    {
        NCBI_THROW(CBlastException, eInvalidArgument,
                   "Error: No query data.");
    }

    // Check if there are any range restrictions applied and if local IDs are
    // being used to determine how to specify the query sequence(s)

    bool has_local_ids = false;

    if (!seqloc_list.empty())
    {
        // Only one range restriction can be sent in this protocol
        if (seqloc_list.front()->IsInt())
        {
            const int kStart((int)seqloc_list.front()->GetStart(eExtreme_Positional));
            const int kStop((int)seqloc_list.front()->GetStop(eExtreme_Positional));
            const int kRangeLength = kStop - kStart + 1;

            _ASSERT(bioseq_set->CanGetSeq_set());
            _ASSERT(!bioseq_set->GetSeq_set().empty());
            _ASSERT(bioseq_set->GetSeq_set().front()->IsSeq());
            _ASSERT(bioseq_set->GetSeq_set().front()->GetSeq().CanGetInst());
            const int kFullLength =
                bioseq_set->GetSeq_set().front()->GetSeq().GetInst().GetLength();

            if (kFullLength != kRangeLength)
            {
            	x_AddParameterToProgramOptions(CBlast4Field::Get(eBlastOpt_RequiredStart), kStart);
            	x_AddParameterToProgramOptions(CBlast4Field::Get(eBlastOpt_RequiredEnd), kStop);
            }
        }

        ITERATE(IRemoteQueryData::TSeqLocs, itr, seqloc_list)
        {
            if (IsLocalId((*itr)->GetId()))
            {
                has_local_ids = true;
                break;
            }
        }
    }

    CObjMgr_QueryFactory* objmgrqf = dynamic_cast<CObjMgr_QueryFactory*>(&*query);
    if ( NULL != objmgrqf )
    {
    	TSeqLocInfoVector user_specified_masks = objmgrqf->ExtractUserSpecifiedMasks();
        if (!user_specified_masks.empty())
        {
        	EBlastProgramType program = NetworkProgram2BlastProgramType(
        									m_QueueSearchRequest->GetProgram(),
        									m_QueueSearchRequest->GetService());

        	CBlast4_get_search_results_reply::TMasks network_masks =
        	    CRemoteBlast::ConvertToRemoteMasks(user_specified_masks, program);

        	NON_CONST_ITERATE(CBlast4_get_search_results_reply::TMasks, itr, network_masks)
        	{
            	CRef<CBlast4_parameter> p(new CBlast4_parameter);
            	p->SetName(CBlast4Field::GetName(eBlastOpt_LCaseMask));

            	CRef<CBlast4_value> v(new CBlast4_value);
            	v->SetQuery_mask(**itr);
            	p->SetValue(*v);
            	_ASSERT(CBlast4Field::Get(eBlastOpt_LCaseMask).Match(*p));

            	m_QueueSearchRequest->SetProgram_options().Set().push_back(p);
        	}