41 #include "../Model/RateDistribution/ConstantRateDistribution.h" 42 #include "../Model/RateDistribution/GammaDiscreteRateDistribution.h" 43 #include "../Model/RateDistribution/GaussianDiscreteRateDistribution.h" 44 #include "../Model/RateDistribution/ExponentialDiscreteRateDistribution.h" 47 #include <Bpp/Text/KeyvalTools.h> 48 #include <Bpp/Numeric/Prob/InvariantMixedDiscreteDistribution.h> 49 #include <Bpp/Numeric/Prob/SimpleDiscreteDistribution.h> 50 #include <Bpp/Numeric/Prob/MixtureOfDiscreteDistributions.h> 51 #include <Bpp/Io/BppOParametrizableFormat.h> 62 const std::string& distDescription,
65 unparsedArguments_.clear();
67 map<string, string> args;
68 KeyvalTools::parseProcedure(distDescription, distName, args);
69 auto_ptr<DiscreteDistribution> rDist;
71 if (distName ==
"Uniform")
72 throw Exception(
"BppO Warning: Uniform distribution is deprecated, use Constant instead.");
74 if ((distName ==
"InvariantMixed") || (distName ==
"Invariant"))
77 string nestedDistDescription = args[
"dist"];
78 if (TextTools::isEmpty(nestedDistDescription))
79 throw Exception(
"BppORateDistributionFormat::read. Missing argument 'dist' for distribution 'Invariant'.");
81 ApplicationTools::displayResult(
"Invariant Mixed distribution", distName );
83 DiscreteDistribution* nestedDistribution = nestedReader.
read(nestedDistDescription,
false);
84 map<string, string> unparsedArgumentsNested(nestedReader.getUnparsedArguments());
87 rDist.reset(
new InvariantMixedDiscreteDistribution(nestedDistribution, 0.1, 0.000001));
90 for (map<string, string>::iterator it = unparsedArgumentsNested.begin();
91 it != unparsedArgumentsNested.end(); it++)
93 unparsedArguments_[
"Invariant." + it->first] = it->second;
96 if (args.find(
"p") != args.end())
97 unparsedArguments_[
"Invariant.p"] = args[
"p"];
99 else if (distName ==
"Constant")
102 throw Exception(
"BppORateDistributionFormat::read(). Constant distribution not allowed.");
104 if (args.find(
"value") != args.end())
105 throw Exception(
"Found argument 'value' in Constant distribution. Constant distribution is defined to have an average of 1.");
108 else if (distName ==
"Simple")
110 if (args.find(
"values") == args.end())
111 throw Exception(
"Missing argument 'values' in Simple distribution");
112 if (args.find(
"probas") == args.end())
113 throw Exception(
"Missing argument 'probas' in Simple distribution");
114 vector<double> probas, values;
116 string rf = args[
"values"];
117 StringTokenizer strtok(rf.substr(1, rf.length() - 2),
",");
118 while (strtok.hasMoreToken())
119 values.push_back(TextTools::toDouble(strtok.nextToken()));
122 StringTokenizer strtok2(rf.substr(1, rf.length() - 2),
",");
123 while (strtok2.hasMoreToken())
124 probas.push_back(TextTools::toDouble(strtok2.nextToken()));
126 std::map<size_t, std::vector<double> > ranges;
128 if (args.find(
"ranges") != args.end())
130 string rr = args[
"ranges"];
131 StringTokenizer strtok3(rr.substr(1, rr.length() - 2),
",");
136 while (strtok3.hasMoreToken())
138 desc = strtok3.nextToken();
140 ppv = desc.find(
";");
142 num = (size_t)(TextTools::toInt(desc.substr(1, po - 1)));
143 deb = TextTools::toDouble(desc.substr(po + 1, ppv - po - 1));
144 fin = TextTools::toDouble(desc.substr(ppv + 1, pf - ppv - 1));
151 if (ranges.size() == 0)
152 rDist.reset(
new SimpleDiscreteDistribution(values, probas));
154 rDist.reset(
new SimpleDiscreteDistribution(values, ranges, probas));
156 vector<string> v = rDist->getParameters().getParameterNames();
158 for (
size_t i = 0; i < v.size(); i++)
160 unparsedArguments_[v[i]] = TextTools::toString(rDist->getParameterValue(rDist->getParameterNameWithoutNamespace(v[i])));
163 else if (distName ==
"Mixture")
165 if (args.find(
"probas") == args.end())
166 throw Exception(
"Missing argument 'probas' in Mixture distribution");
167 vector<double> probas;
168 vector<DiscreteDistribution*> v_pdd;
169 string rf = args[
"probas"];
170 StringTokenizer strtok2(rf.substr(1, rf.length() - 2),
",");
171 while (strtok2.hasMoreToken())
172 probas.push_back(TextTools::toDouble(strtok2.nextToken()));
174 vector<string> v_nestedDistrDescr;
177 while (args.find(
"dist" + TextTools::toString(++nbd)) != args.end())
178 v_nestedDistrDescr.push_back(args[
"dist" + TextTools::toString(nbd)]);
180 if (v_nestedDistrDescr.size() != probas.size())
181 throw Exception(
"Number of distributions (keyword 'dist" + TextTools::toString(probas.size()) +
"') do not fit the number of probabilities");
183 for (
unsigned i = 0; i < v_nestedDistrDescr.size(); i++)
186 auto_ptr<DiscreteDistribution> pdd(nestedReader.
read(v_nestedDistrDescr[i],
false));
187 map<string, string> unparsedArgumentsNested(nestedReader.getUnparsedArguments());
189 for (map<string, string>::iterator it = unparsedArgumentsNested.begin(); it != unparsedArgumentsNested.end(); it++)
191 unparsedArguments_[distName +
"." + TextTools::toString(i + 1) +
"_" + it->first] = it->second;
193 v_pdd.push_back(pdd.release());
195 rDist.reset(
new MixtureOfDiscreteDistributions(v_pdd, probas));
199 if (args.find(
"n") == args.end())
200 throw Exception(
"Missing argument 'n' (number of classes) in " + distName
202 size_t nbClasses = TextTools::to<size_t>(args[
"n"]);
204 if (distName ==
"Gamma")
208 if (args.find(
"alpha") != args.end())
209 unparsedArguments_[
"Gamma.alpha"] = args[
"alpha"];
210 if (args.find(
"beta") != args.end())
211 throw Exception(
"Found argument 'beta' in Gamma distribution. Gamma distribution is defined to have an average of 1, with beta=alpha.");
213 else if (distName ==
"Gaussian")
216 if (args.find(
"mu") != args.end())
217 throw Exception(
"Found argument 'mu' in Gaussian distribution. Gaussian distribution is defined to have an average of 1, with mu=1.");
218 if (args.find(
"sigma") != args.end())
219 unparsedArguments_[
"Gaussian.sigma"] = args[
"sigma"];
221 else if (distName ==
"Exponential")
224 if (args.find(
"lambda") != args.end())
225 throw Exception(
"Found argument 'lambda' in Exponential distribution. Exponential distribution is defined to have an average of 1, with lambda=1.");
229 throw Exception(
"Unsupported rate distribution: " + distName +
".");
234 ApplicationTools::displayResult(
"Distribution", distName);
235 ApplicationTools::displayResult(
"Number of classes", TextTools::toString(rDist->getNumberOfCategories()));
241 return rDist.release();
246 const DiscreteDistribution& dist,
248 std::map<std::string, std::string>& globalAliases,
249 std::vector<std::string>& writtenNames)
const 253 const DiscreteDistribution* pd;
255 out << dist.getName() +
"(";
257 const InvariantMixedDiscreteDistribution* invar =
dynamic_cast<const InvariantMixedDiscreteDistribution*
>(&dist);
260 pd = invar->getVariableSubDistribution();
262 write(*pd, out, globalAliases, writtenNames);
267 const MixtureOfDiscreteDistributions* mix =
dynamic_cast<const MixtureOfDiscreteDistributions*
>(&dist);
270 size_t nd = mix->getNumberOfDistributions();
271 for (
size_t i = 0; i < nd; i++)
275 out <<
"dist" + TextTools::toString(i + 1) +
"=";
276 write(*mix->getNDistribution(i), out, globalAliases, writtenNames);
280 for (
size_t i = 0; i < nd; i++)
282 out << mix->getNProbability(i);
287 for (
size_t i = 1; i < nd; i++)
289 writtenNames.push_back(mix->getNamespace() +
"theta" + TextTools::toString(i));
293 if (dynamic_cast<const ExponentialDiscreteRateDistribution*>(&dist) ||
295 dynamic_cast<const GaussianDiscreteRateDistribution*>(&dist))
299 out <<
"n=" << dist.getNumberOfCategories();
303 const SimpleDiscreteDistribution* ps =
dynamic_cast<const SimpleDiscreteDistribution*
>(&dist);
306 size_t nd = ps->getNumberOfCategories();
310 for (
size_t i = 0; i < nd; i++)
312 out << ps->getCategory(i);
317 for (
size_t i = 0; i < nd; i++)
319 out << ps->getProbability(i);
325 const std::map<size_t, std::vector<double> > range = ps->getRanges();
326 if (range.size() != 0)
329 std::map<size_t, std::vector<double> >::const_iterator it(range.begin());
330 while (it != range.end())
332 out <<
"V" << TextTools::toString(it->first);
333 out <<
"[" << TextTools::toString(it->second[0]) <<
";" << TextTools::toString(it->second[1]) <<
"]";
335 if (it != range.end())
342 for (
size_t i = 1; i < nd; i++)
344 writtenNames.push_back(ps->getNamespace() +
"theta" + TextTools::toString(i));
346 for (
size_t i = 1; i < nd + 1; i++)
348 writtenNames.push_back(ps->getNamespace() +
"V" + TextTools::toString(i));
356 BppOParametrizableFormat bOP;
357 bOP.write(dynamic_cast<const ParameterAliasable*>(&dist), out, globalAliases, dist.getIndependentParameters().getParameterNames(), writtenNames,
true, comma);