예제 #1
0
void ShaderCompiler::processChangedFiles()
{
	if (m_is_compiling) return;

	char changed_file_path[Lumix::MAX_PATH_LENGTH];
	{
		Lumix::MT::SpinLock lock(m_mutex);
		if (m_changed_files.empty()) return;

		m_changed_files.removeDuplicates();
		const char* tmp = m_changed_files.back().c_str();
		Lumix::copyString(changed_file_path, sizeof(changed_file_path), tmp);
		m_changed_files.pop();
	}
	Lumix::string tmp_string(changed_file_path, m_editor.getAllocator());
	int find_idx = m_dependencies.find(tmp_string);
	if (find_idx < 0)
	{
		int len = Lumix::stringLength(changed_file_path);
		if (len <= 6) return;

		if (Lumix::compareString(changed_file_path + len - 6, "_fs.sc") == 0 ||
			Lumix::compareString(changed_file_path + len - 6, "_vs.sc") == 0)
		{
			Lumix::copyString(
				changed_file_path + len - 6, Lumix::lengthOf(changed_file_path) - len + 6, ".shd");
			tmp_string = changed_file_path;
			find_idx = m_dependencies.find(tmp_string);
		}
	}
	if (find_idx >= 0)
	{
		if (Lumix::PathUtils::hasExtension(changed_file_path, "shd"))
		{
			compile(changed_file_path);
		}
		else
		{
			Lumix::Array<Lumix::string> src_list(m_editor.getAllocator());

			for (auto& bin : m_dependencies.at(find_idx))
			{
				char basename[Lumix::MAX_PATH_LENGTH];
				Lumix::PathUtils::getBasename(basename, sizeof(basename), bin.c_str());
				char tmp[Lumix::MAX_PATH_LENGTH];
				getSourceFromBinaryBasename(tmp, sizeof(tmp), basename);
				Lumix::string src(tmp, m_editor.getAllocator());
				src_list.push(src);
			}

			src_list.removeDuplicates();

			for (auto& src : src_list)
			{
				compile(src.c_str());
			}
		}
	}
}
예제 #2
0
void ShaderCompiler::makeUpToDate()
{
	auto* iter = PlatformInterface::createFileIterator("shaders", m_editor.getAllocator());

	Lumix::Array<Lumix::string> src_list(m_editor.getAllocator());
	auto& fs = m_editor.getEngine().getFileSystem();
	PlatformInterface::FileInfo info;
	while (getNextFile(iter, &info))
	{
		char basename[Lumix::MAX_PATH_LENGTH];
		Lumix::PathUtils::getBasename(basename, sizeof(basename), info.filename);
		if (!Lumix::PathUtils::hasExtension(info.filename, "shd")) continue;
		const char* shd_path = StringBuilder<Lumix::MAX_PATH_LENGTH>(
			"shaders/", info.filename);
		auto* file = fs.open(fs.getDiskDevice(),
							 shd_path,
							 Lumix::FS::Mode::OPEN_AND_READ);

		if (!file)
		{
			Lumix::g_log_error.log("shader compiler") << "Could not open "
													  << info.filename;
			continue;
		}

		int len = (int)file->size();
		Lumix::Array<char> data(m_editor.getAllocator());
		data.resize(len+1);
		file->read(&data[0], len);
		data[len] = 0;
		fs.close(*file);

		Lumix::ShaderCombinations combinations;
		Lumix::Shader::getShaderCombinations(
			getRenderer(), &data[0], &combinations);

		const char* bin_base_path =
			StringBuilder<Lumix::MAX_PATH_LENGTH>("shaders/compiled/", basename, "_");
		if (isChanged(combinations, bin_base_path, shd_path))
		{
			src_list.emplace(shd_path, m_editor.getAllocator());
		}
	}

	PlatformInterface::destroyFileIterator(iter);

	for (int i = 0; i < m_dependencies.size(); ++i)
	{
		auto& key = m_dependencies.getKey(i);
		auto& value = m_dependencies.at(i);
		for (auto& bin : value)
		{
			if (!Lumix::fileExists(bin.c_str()) ||
				Lumix::getLastModified(bin.c_str()) < Lumix::getLastModified(key.c_str()))
			{
				char basename[Lumix::MAX_PATH_LENGTH];
				Lumix::PathUtils::getBasename(basename, sizeof(basename), bin.c_str());
				char tmp[Lumix::MAX_PATH_LENGTH];
				getSourceFromBinaryBasename(tmp, sizeof(tmp), basename);
				Lumix::string src(tmp, m_editor.getAllocator());
				src_list.push(src);
			}
		}
	}
	
	src_list.removeDuplicates();
	for (auto src : src_list)
	{
		compile(src.c_str());
	}
}
예제 #3
0
파일: transtree.cpp 프로젝트: windnc/alex
bool CTransTree::ApplyTransLexical( CUStringListRO &list )
{
	CUString src_trans_rule = list.GetAt(0);
	CUString tgt_trans_rule = list.GetAt(1);

	CUStringListRO src_list( src_trans_rule, " " );
	CUStringListRO tgt_list( tgt_trans_rule, " " );

	int start_idx = -1;
	int end_idx = -1;
	for( int i=0; i<(int)leaf_node_vec.size()-src_list.GetSize(); i++ ) {
		bool match = true;
		for( int j=0; j<src_list.GetSize(); j++ ) {
			if( leaf_node_vec[i+j]->label != src_list.GetAt(j) ) {
				match = false;
				break;
			}
		}
		if( match == true ) {
			start_idx = i;
			end_idx = i+src_list.GetSize()-1;
			break;
		}
	}

	if( start_idx != -1 ) {
		CTransTreeNode *target_node = root;
		while( true ) {
			bool changed = false;
			for( int i=0; i<(int)target_node->child_vec.size(); i++ ) {
				CTransTreeNode* child_node = target_node->child_vec[i];
				if( child_node->is_terminal == true )	continue;
				if( child_node->span_begin <= start_idx && child_node->span_end >= end_idx ) {
					target_node = child_node;
					changed = true;
					break;
				}
			}
			if( changed == false )	break;
			//fprintf( stderr, "Find: %s (%d~%d)\n", target_node->label.GetStr(), start_idx, end_idx );
		}

		for( int i=(int)target_node->child_vec.size()-1; i>=0; i-- ) {
			CTransTreeNode* child = target_node->child_vec[i];
			if( child->span_begin >= start_idx && child->span_end <= end_idx ) {
				target_node->RemoveChild( child );
			}
		}

		CTransTreeNode* new_child = new CTransTreeNode();
		new_child->label = "#";
		new_child->is_terminal = true;
		new_child->span_begin = start_idx;
		new_child->span_end = end_idx;
		for( int j=0; j<tgt_list.GetSize(); j++ ) {
			if( j > 0 )	new_child->trans += " ";
			new_child->trans += tgt_list.GetAt(j);
		}
		target_node->AddChild( new_child );

		/*
		CTransTreeNode *target_node = root;
		while( true ) {
			bool changed = false;
			for( int i=0; i<(int)target_node->child_vec.size(); i++ ) {
				CTransTreeNode* child_node = target_node->child_vec[i];
				if( child_node->span_begin <= start_idx && child_node->span_end >= end_idx ) {
					target_node = child_node;
					changed = true;
					break;
				}
			}
			if( changed == false )	break;
		}
		root->AddChild( new_child );
		*/

	}



	return true;

	vector<CTransTreeNode*> node_stack;
	node_stack.push_back( root );
	while( node_stack.size() > 0 ) {
		CTransTreeNode* node = node_stack.back(); node_stack.pop_back();
		fprintf( stderr, "%s\n", node->label.GetStr() );
		for( int i=0; i<(int)node->child_vec.size(); i++ ) {
			fprintf( stderr, "   %s\n", node->child_vec[i]->label.GetStr() );
		}

		/*
		if( node->child_vec.size() == src_list.GetSize() ) {
			bool match = true;
			for( int a=0; a<src_list.GetSize(); a++ ) {
				CUString tmp_str = src_list.GetAt(a);
				// lexical
				if( tmp_str.Count("/") == 1 ) {
					if( node->child_vec[a]->label != tmp_str ) {
						match = false;
						break;
					}
				}
				// label
				else {
					if( node->child_vec[a]->label != tmp_str ) {
						match = false;
						break;
					}
				}
			}
			if( match == true ) {
				// delete src lexical
				for( int i=0; i<node->child_vec.size(); i++ ) {
					if( node->child_vec[i]->is_terminal == true ) {
						node->RemoveChild( node->child_vec[i] );
					}
					else {
					}
				}

				// add tgt lexical + src label reorder
				for( int i=0; i<tgt_list.GetSize(); i++ ) {
					CUString tmp_str = tgt_list.GetAt(i);
					if( tmp_str.Count("/") == 1 ) {
						CTransTreeNode* new_node = new CTransTreeNode();
						new_node->label = "#";
						new_node->is_terminal = true;
						new_node->trans = tgt_list.GetAt(i);
						new_node->parent = node;
						new_node->trans_order = i;
						node->AddChild( new_node );
					}
					else {
						if( tmp_str == "@1" ) {
							CTransTreeNode* tmp_node = node->GetNthNonterminal( 1 );
							if( tmp_node == NULL ) {
								//fprintf( stderr, "fail @1 %d\n", i );
							}
							else {
								//fprintf( stderr, "succ %s %d\n", tmp_node->label.GetStr(), i );
								tmp_node->trans_order = i;
							}
						}
						else if( tmp_str == "@2" ) {
							CTransTreeNode* tmp_node = node->GetNthNonterminal( 2 );
							if( tmp_node == NULL ) {
								//fprintf( stderr, "fail @2 %d\n", i );
							}
							else {
								//fprintf( stderr, "succ %s %d\n", tmp_node->label.GetStr(), i );
								tmp_node->trans_order = i;
							}
						}
					}
				}
			}
		}
		*/
		for( int i=0; i<(int)node->child_vec.size(); i++ ) {
			node_stack.push_back( node->child_vec[i] );
		}
	}

	return true;
}
예제 #4
0
파일: transtree.cpp 프로젝트: windnc/alex
bool CTransTree::ApplyTransRule( CUStringListRO &list )
{
	CUString src_trans_rule = list.GetAt(0);
	CUString tgt_trans_rule = list.GetAt(1);

	CUStringListRO src_list( src_trans_rule, " " );
	CUStringListRO tgt_list( tgt_trans_rule, " " );


	vector<CTransTreeNode*> node_stack;
	node_stack.push_back( root );
	while( node_stack.size() > 0 ) {
		CTransTreeNode* node = node_stack.back(); node_stack.pop_back();
		/*
		fprintf( stderr, "%s\n", node->label.GetStr() );
		for( int i=0; i<(int)node->child_vec.size(); i++ ) {
			fprintf( stderr, "   %s\n", node->child_vec[i]->label.GetStr() );
		}
		*/

		if( node->child_vec.size() == src_list.GetSize() ) {
			bool match = true;
			for( int a=0; a<src_list.GetSize(); a++ ) {
				CUString tmp_str = src_list.GetAt(a);
				// lexical
				if( tmp_str.Count("/") == 1 ) {
					if( node->child_vec[a]->label != tmp_str ) {
						match = false;
						break;
					}
				}
				// label
				else {
					if( node->child_vec[a]->label != tmp_str ) {
						match = false;
						break;
					}
				}
			}
			if( match == true ) {
				// delete src lexical
				for( int i=(int)node->child_vec.size()-1; i>=0; i-- ) {
					if( node->child_vec[i]->is_terminal == true ) {
						node->RemoveChild( node->child_vec[i] );
					}
					else {
					}
				}

				// add tgt lexical + src label reorder
				for( int i=0; i<tgt_list.GetSize(); i++ ) {
					CUString tmp_str = tgt_list.GetAt(i);
					if( tmp_str.Count("/") == 1 ) {
						CTransTreeNode* new_node = new CTransTreeNode();
						new_node->label = "#";
						new_node->is_terminal = true;
						new_node->trans = tgt_list.GetAt(i);
						new_node->parent = node;
						new_node->trans_order = i;
						node->AddChild( new_node );
					}
					else {
						if( tmp_str == "@1" ) {
							CTransTreeNode* tmp_node = node->GetNthNonterminal( 1 );
							if( tmp_node == NULL ) {
								//fprintf( stderr, "fail @1 %d\n", i );
							}
							else {
								//fprintf( stderr, "succ %s %d\n", tmp_node->label.GetStr(), i );
								tmp_node->trans_order = i;
							}
						}
						else if( tmp_str == "@2" ) {
							CTransTreeNode* tmp_node = node->GetNthNonterminal( 2 );
							if( tmp_node == NULL ) {
								//fprintf( stderr, "fail @2 %d\n", i );
							}
							else {
								//fprintf( stderr, "succ %s %d\n", tmp_node->label.GetStr(), i );
								tmp_node->trans_order = i;
							}
						}
					}
				}
			}
		}
		for( int i=0; i<(int)node->child_vec.size(); i++ ) {
			node_stack.push_back( node->child_vec[i] );
		}
	}

	return true;
}
예제 #5
0
void test_swap (T*,
                Allocator                      &a1,
                Allocator                      &a2,
                const ContainerTestCaseData<T> &tdata)
{
    typedef std::list <T, Allocator> List;
    typedef ListState<List>          ListState;

    const ContainerTestCase &tcase = tdata.tcase_;
    const ContainerFunc     &func  = tdata.func_;

    // construct the list object to be modified
    // and the argument list
    List src_list (tdata.str_, tdata.str_ + tdata.strlen_, a1);
    List dst_list (tdata.arg_, tdata.arg_ + tdata.arglen_, a2);

    List& arg_list            = tcase.arg ? dst_list : src_list;

    // save the state of the list object before the call
    // to detect exception safety violations (changes to
    // the state of the object after an exception)
    const ListState src_state (src_list);
    const ListState arg_state (arg_list);

    rwt_free_store* const pst = rwt_get_free_store (0);
    SharedAlloc*    const pal = SharedAlloc::instance ();

    // iterate for`throw_count' starting at the next call to operator new,
    // forcing each call to throw an exception, until the function finally
    // succeeds (i.e, no exception is thrown)
    std::size_t throw_count;
    for (throw_count = 0; ; ++throw_count) {

        const char* expected = 0;
        const char* caught = 0;

#ifndef _RWSTD_NO_EXCEPTIONS

        // no exceptions expected
        if (0 == tcase.bthrow && a1 == a2) {
            // by default exercise the exception safety of the function
            // by iteratively inducing an exception at each call to operator
            // new or Allocator::allocate() until the call succeeds
            expected = exceptions [1];      // bad_alloc
            *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
            pal->throw_at_calls_ [pal->m_allocate] =
                pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
        }

#else   // if defined (_RWSTD_NO_EXCEPTIONS)

        if (tcase.bthrow)
            return;

#endif   // _RWSTD_NO_EXCEPTIONS

        // start checking for memory leaks
        rw_check_leaks (src_list.get_allocator ());
        rw_check_leaks (arg_list.get_allocator ());

        try {
            const bool is_class = ListIds::UserClass == func.elem_id_;

            // reset function call counters
            if (is_class)
                UserClass::reset_totals ();

            src_list.swap (arg_list);

            if (is_class && a1 == a2) {

                bool success =  0 == (UserClass::n_total_def_ctor_
                                    | UserClass::n_total_copy_ctor_
                                    | UserClass::n_total_op_assign_);

                rw_assert (success, 0, tcase.line, 
                           "line %d. %{$FUNCALL}: complexity: %zu def ctors, "
                           "%zu copy ctors, %zu assigns", __LINE__,
                           UserClass::n_total_def_ctor_,
                           UserClass::n_total_copy_ctor_,
                           UserClass::n_total_op_assign_);
            }

            if (0 == tcase.str) {

                rw_assert (0 == arg_list.size (), 0, tcase.line, 
                           "line %d. %{$FUNCALL}: expected 0 size, "
                           "got %zu",  __LINE__, arg_list.size ());
            }

            if (a1 == a2) {

                src_state.assert_equal (ListState (arg_list),
                    __LINE__, tcase.line, "swap");

                arg_state.assert_equal (ListState (src_list),
                    __LINE__, tcase.line, "swap");
            }
        }

#ifndef _RWSTD_NO_EXCEPTIONS

        catch (const std::bad_alloc &ex) {
            caught = exceptions [1];
            rw_assert (0 == tcase.bthrow, 0, tcase.line,
                       "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                       "unexpectedly%{;} caught std::%s(%#s)",
                       __LINE__, 0 != expected, expected, caught, ex.what ());
        }
        catch (const std::exception &ex) {
            caught = exceptions [2];
            rw_assert (0, 0, tcase.line,
                       "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                       "unexpectedly%{;} caught std::%s(%#s)",
                       __LINE__, 0 != expected, expected, caught, ex.what ());
        }
        catch (...) {
            caught = exceptions [0];
            rw_assert (0, 0, tcase.line,
                       "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                       "unexpectedly%{;} caught %s",
                       __LINE__, 0 != expected, expected, caught);
        }

#endif   // _RWSTD_NO_EXCEPTIONS

        // FIXME: verify the number of blocks the function call
        // is expected to allocate and detect any memory leaks
        rw_check_leaks (src_list.get_allocator (), tcase.line,
                        std::size_t (-1), std::size_t (-1));

        rw_check_leaks (arg_list.get_allocator (), tcase.line,
                        std::size_t (-1), std::size_t (-1));

        if (caught) {
            // verify that an exception thrown during allocation
            // didn't cause a change in the state of the object
            src_state.assert_equal (ListState (src_list),
                                    __LINE__, tcase.line, caught);

            arg_state.assert_equal (ListState (arg_list),
                                    __LINE__, tcase.line, caught);

            if (0 == tcase.bthrow) {
                // allow this call to operator new to succeed and try
                // to make the next one to fail during the next call
                // to the same function again
                continue;
            }
        }
        else if (0 < tcase.bthrow) {
            rw_assert (caught == expected, 0, tcase.line,
                       "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
                       "%{:}unexpectedly caught %s%{;}",
                       __LINE__, 0 != expected, expected, caught, caught);
        }

        break;
    }

    // no exception expected
    const std::size_t expect_throws = 0;

    rw_assert (expect_throws == throw_count, 0, tcase.line,
               "line %d: %{$FUNCALL}: expected exactly 0 %s exception "
               "while the swap, got %zu",
               __LINE__, exceptions [1], throw_count);

    // disable bad_alloc exceptions
    *pst->throw_at_calls_ [0] = 0;
    pal->throw_at_calls_ [pal->m_allocate] = 0;
}
int
centroid_alifold(int argc, char* argv[])
{
  std::vector<float> gamma;
  std::vector<float> th;
  std::vector<std::string> engine;
  std::vector<float> mix_w;
  std::string input;
  std::vector<std::string> model;
  float p_th=0.0;
  std::string p_outname;
  std::string outname;
  std::string ps_outname;
  uint max_bp_dist;
  std::string param;
  uint max_clusters;
  uint num_samples=0;
  uint seed;
  //
  int num_ea_samples = -1;
  int max_mcc = -1;
  
  // parse command line options
  po::options_description desc("Options");
  desc.add_options()
    ("help,h", "show this message")
#ifdef HAVE_LIBRNA
    ("engine,e", po::value<std::vector<std::string> >(&engine),
     "specify the inference engine (default: \"McCaskill & Alifold\")")
#else
    ("engine,e", po::value<std::vector<std::string> >(&engine),
     "specify the inference engine (default: \"CONTRAfold\")")
#endif
    ("mixture,w", po::value<std::vector<float> >(&mix_w), "mixture weights of inference engines")
    ("gamma,g", po::value<std::vector<float> >(&gamma), "weight of base pairs")
    ("threshold,t", po::value<std::vector<float> >(&th),
     "thereshold of base pairs (this option overwrites 'gamma')")
    //
    ("ea", po::value<int>(&num_ea_samples), 
     "compute (pseudo-)expected accuracy (pseudo if arg==0, sampling if arg>0; arg: # of sampling)")
    ("max-mcc", po::value<int>(&max_mcc), 
     "predict secondary structure by maximizing pseudo-expected MCC (arg: # of sampling)")
    // added by M. Hamada
    ("mea", "run as an MEA estimator")
    ("noncanonical", "allow non-canonical base-pairs")
    ("constraints,C", "use structure constraints")
    ("output,o", po::value<std::string>(&outname),
     "specify filename to output predicted secondary structures. If empty, use the standard output.")
    ("posteriors", po::value<float>(&p_th),
     "output base-pairing probability matrices which contain base-pairing probabilities more than the given value.")
    ("posteriors-output", po::value<std::string>(&p_outname),
     "specify filename to output base-pairing probability matrices. If empty, use the standard output.")
    ("postscript", po::value<std::string>(&ps_outname),
     "draw predicted secondary structures with the postscript (PS) format")
    /*("monochrome", "draw the postscript with monochrome")*/
    ("params", po::value<std::string>(&param), "use the parameter file");

  po::options_description opts_contrafold("Options for CONTRAfold model");
  opts_contrafold.add_options()
#if 0 // HAVE_LIBRNA // move to hidden options
    ("alipf_fold", "use alipf_fold base-pairing probabilities rather than those of CONTRAfold model")
    ("pf_fold", "use pf_fold base-pairing probabilities rather than those of CONTRAfold model")
#endif
    ("max-dist,d", po::value<uint>(&max_bp_dist)->default_value(0),
     "the maximum distance of base-pairs");

  po::options_description opts_sampling("Options for sampling");
  opts_sampling.add_options()
    ("sampling,s", 
     po::value<uint>(&num_samples),
     "specify the number of samples to be generated for each sequence")
    ("max-clusters,c",
     po::value<uint>(&max_clusters)->default_value(10),
     "the maximum number of clusters for the stochastic sampling algorithm")
    ("seed",
     po::value<uint>(&seed)->default_value(0),
     "specify the seed for the random number generator (set this automatically if seed=0)");

  po::options_description opts("Options");
  opts.add_options()
#ifdef HAVE_LIBRNA
    ("alipf_fold", "use alipf_fold base-pairing probabilities rather than those of CONTRAfold model")
    ("pf_fold", "use pf_fold base-pairing probabilities rather than those of CONTRAfold model")
#endif
    ("aux", "use auxiliary base-pairing probabilities")
    ("monochrome", "draw the postscript with monochrome")
    ("seq-file", po::value<std::string>(&input), "training sequence filename")
    ("model-file", po::value<std::vector<std::string> >(&model), "model filename");

  opts.add(desc);
  opts.add(opts_contrafold);
  opts.add(opts_sampling);
  po::positional_options_description pd;
  pd.add("seq-file", 1); pd.add("model-file", -1);
  po::variables_map vm;
  bool usage=false;
  try {
    po::parsed_options parsed =
      po::command_line_parser(argc, argv).options(opts).positional(pd).run();
    po::store(parsed, vm);
    po::notify(vm);
  } catch (...) {
    usage=true;
  }

  if (usage || vm.count("help") || !vm.count("seq-file") ||
      (vm.count("aux") && model.empty()))
  {
    std::string features("CONTRAfold");
#ifdef HAVE_LIBRNA
    features += ", McCaskill";
    features += ", Alifold";
#endif
    features += ", pfold";
    features += ", AUX";

    std::cout << "CentroidAlifold v" << VERSION 
	      << " for predicting common RNA secondary structures" << std::endl
	      << "  (available engines: " << features << ")" << std::endl
	      << "Usage:" << std::endl
	      << " " << argv[0]
	      << " [options] seq [bp_matrix ...]\n\n"
	      << desc << std::endl
              << opts_contrafold << std::endl
              << opts_sampling << std::endl;
    return 1;
  }

  BOOST_SPIRIT_CLASSIC_NS::file_iterator<> fi(input.c_str());
  if (!fi)
  {
    perror(input.c_str());
    return 1;
  }

  if (th.size()>0)
  {
    gamma.resize(th.size());
    for (uint i=0; i!=th.size(); ++i)
      gamma[i] = 1.0/th[i]-1.0;
  }

  if (gamma.size()==1 && gamma[0]<0.0)
  {
    float g[] = { 0.03125, 0.0625, 0.125, 0.25, 0.5, 1.0, 2.0, 4.0, 6.0,
                  8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0 };
    gamma.resize(boost::size(g));
    std::copy(boost::begin(g), boost::end(g), gamma.begin());
  }

  if (engine.empty())
  {
#ifdef HAVE_LIBRNA
    engine.push_back("McCaskill");
    engine.push_back("Alifold");
#else
    engine.push_back("CONTRAfold");
#endif
  }
  if (vm.count("pf_fold")) { engine.resize(1); engine[0]="McCaskill"; }
  if (vm.count("alipf_fold")) { engine.resize(1); engine[0]="Alifold"; }
  if (vm.count("aux")) { engine.resize(1); engine[0]="AUX"; }

  FoldingEngine<Aln>* cf=NULL;
  std::vector<FoldingEngine<Aln>*> cf_list(engine.size(), NULL);
  std::vector<FoldingEngine<std::string>*> src_list(engine.size(), NULL);
  for (uint i=0; i!=engine.size(); ++i)
  {
    if (engine[i]=="CONTRAfold")
    {
      if (gamma.empty()) gamma.push_back(vm.count("mea") ? 6.0 : 4.0);
      src_list[i] = new CONTRAfoldModel(param, !vm.count("noncanonical"), max_bp_dist, seed, vm.count("mea"));
      cf_list[i] = new AveragedModel(src_list[i], max_bp_dist, vm.count("mea"));
    }
    else if (engine[i]=="CONTRAfoldM")
    {
      if (gamma.empty()) gamma.push_back(vm.count("mea") ? 6.0 : 4.0);
      cf_list[i] = new CONTRAfoldMultiModel(param, !vm.count("noncanonical"), max_bp_dist, seed, vm.count("mea"));
    }
#ifdef HAVE_LIBRNA
    else if (engine[i]=="McCaskill")
    {
      if (gamma.empty()) gamma.push_back(vm.count("mea") ? 6.0 : 2.0);
      src_list[i] = new McCaskillModel(!vm.count("noncanonical"), max_bp_dist,
                                       param.empty() ? NULL : param.c_str(),
                                       seed, vm.count("mea"));
      cf_list[i] = new AveragedModel(src_list[i], max_bp_dist, vm.count("mea"));
    }
    else if (engine[i]=="Alifold")
    {
      if (gamma.empty()) gamma.push_back(vm.count("mea") ? 6.0 : 2.0);
      cf_list[i] = new AliFoldModel(!vm.count("noncanonical"), max_bp_dist,
                                    param.empty() ? NULL : param.c_str(),
                                    seed, vm.count("mea"));
    }
#endif
    else if (engine[i]=="pfold")
    {
      if (gamma.empty()) gamma.push_back(vm.count("mea") ? 6.0 : 1.0);
      std::string pfold_bin_dir(getenv("PFOLD_BIN_DIR") ? getenv("PFOLD_BIN_DIR") : ".");
      std::string awk_bin(getenv("AWK_BIN") ? getenv("AWK_BIN") : "mawk");
      std::string sed_bin(getenv("SED_BIN") ? getenv("SED_BIN") : "sed");
      cf_list[i] = new PfoldModel<Aln>(pfold_bin_dir, awk_bin, sed_bin, vm.count("mea"));
    }
    else if (engine[i]=="AUX")
    {
      if (gamma.empty()) gamma.push_back(vm.count("mea") ? 6.0 : 1.0);
      src_list[i] = new AuxModel(model, vm.count("mea"));
      cf_list[i] = new AveragedModel(src_list[i], 0, vm.count("mea"));
    }
    else
    {
      throw std::logic_error("unsupported engine");
    }
  }

  if (engine.size()==1)
    cf=cf_list[0];
  else
  {
    if (gamma.empty()) gamma.push_back(vm.count("mea") ? 6.0 : 1.0);
    std::vector<std::pair<FoldingEngine<Aln>*,float> > models;
    for (uint i=0; i!=engine.size(); ++i)
    {
      if (engine.size()!=mix_w.size())
        models.push_back(std::make_pair(cf_list[i], 1.0));
      else
        models.push_back(std::make_pair(cf_list[i], mix_w[i]));
    }
    cf = new MixtureModel<Aln>(models, vm.count("mea"));
  }
  
  std::ostream* out = &std::cout;
  if (vm.count("output"))
  {
    out = new std::ofstream(outname.c_str());
    if (out->fail())
    {
      perror(outname.c_str());
      delete out;
      return 1;
    }
  }

  std::ostream* p_out = &std::cout;
  if (vm.count("posteriors") && vm.count("posteriors-output") && !vm.count("sampling"))
  {
    p_out = new std::ofstream(p_outname.c_str());
    if (p_out->fail())
    {
      perror(p_outname.c_str());
      delete p_out;
      return 1;
    }
  }

  Aln aln;
  uint n=0;
  uint bytes=0;
  uint total_bytes=0;
  while ((bytes=aln.load(fi))>0)
  {
    n++;
    total_bytes+=bytes;

    std::list<std::string>::iterator seq;
    for (seq=aln.seq().begin(); seq!=aln.seq().end(); ++seq)
    {
      std::replace(seq->begin(), seq->end(), 't', 'u');
      std::replace(seq->begin(), seq->end(), 'T', 'U');
    }

    if (vm.count("constraints"))
    {
      std::cout << "Input constraints:" << std::endl;
      std::string str;
      std::getline(std::cin, str);
      cf->set_constraint(str);
    }

    if (num_samples>0)
    {
      if (max_clusters>0)
        cf->stochastic_fold(aln.name().front(), aln, num_samples, gamma, max_clusters, *out, p_outname, p_th);
      else
        cf->stochastic_fold(aln, num_samples, *out);
      continue;
    }

    if (max_mcc>0)
    {
      cf->max_mcc_fold(aln.name().front(), aln, *out, max_mcc);
      continue;
    }

    if (num_ea_samples>=0)
      cf->centroid_fold(aln.name().front(), aln, gamma, *out, num_ea_samples);
    else
      cf->centroid_fold(aln.name().front(), aln, gamma, *out);

    if (vm.count("posteriors")) cf->get_bp().save(*p_out, aln.consensus(), p_th);

    if (!ps_outname.empty())
    {
      char buf[PATH_MAX];
      if (n==1)
        strncpy(buf, ps_outname.c_str(), sizeof(buf));
      else
        snprintf(buf, sizeof(buf), "%s-%d", ps_outname.c_str(), n-1);
      cf->ps_plot(std::string(buf), aln, gamma[0], !vm.count("monochrome"));
    }
  }
  if (fi!=fi.make_end())
    std::cout << "parse error after " << total_bytes << " bytes were loaded" << std::endl;

  if (engine.size()!=1 && cf) delete cf;
  for (uint i=0; i!=cf_list.size(); ++i) if (cf_list[i]) delete cf_list[i];
  for (uint i=0; i!=src_list.size(); ++i) if (src_list[i]) delete src_list[i];
  if (out != &std::cout) delete out;
  if (p_out != &std::cout) delete p_out;

  return 0;
}