source: cpp/frams/genetics/geno.cpp @ 508

Last change on this file since 508 was 508, checked in by Maciej Komosinski, 8 years ago

Conditional macro to identify for which genotypes the order of genotype validators matters

  • Property svn:eol-style set to native
File size: 7.3 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
[109]4
5#include "geno.h"
[145]6#include "genoconv.h"
[452]7#include <common/loggers/loggers.h>
8#include <common/stl-util.h>
[109]9#include <frams/model/model.h>
10
[348]11THREAD_LOCAL_DEF_PTR(Geno::Validators, geno_validators);
12THREAD_LOCAL_DEF_PTR(GenoConvManager, geno_converters);
[109]13
[348]14Geno::Validators* Geno::getValidators() {return tlsGetPtr(geno_validators);}
15GenoConvManager* Geno::getConverters() {return tlsGetPtr(geno_converters);}
[346]16
[348]17Geno::Validators* Geno::useValidators(Validators* val)
18{return tlsSetPtr(geno_validators,val);}
19GenoConvManager* Geno::useConverters(GenoConvManager* gcm)
20{return tlsSetPtr(geno_converters,gcm);}
[346]21
[150]22void Geno::init(const SString& genstring, char genformat, const SString& genname, const SString& comment)
[109]23{
[150]24        refcount = 1;
25        owner = 0;
26        f0gen = 0;
27        mapinshift = 0;
28        mapoutshift = 0;
29        isvalid = -1;
30        SString gencopy(genstring);
31        if (genformat == -1)
[109]32        { // unknown format
[150]33                genformat = '1';
34                if (genstring.charAt(0) == '/')
[109]35                {
[150]36                        int end;
37                        SString newcomment;
38                        switch (genstring.charAt(1))
[109]39                        {
40                        case '/':
[150]41                                genformat = genstring.charAt(2);
42                                if ((end = genstring.indexOf('\n')) >= 0)
43                                {
44                                        newcomment = genstring.substr(2, end - 2);
45                                        gencopy = genstring.substr(end + 1);
46                                        mapinshift = end + 1;
47                                }
[109]48                                else
[150]49                                {
50                                        gencopy = 0;
51                                        mapinshift = genstring.len();
52                                }
[109]53                                break;
54                        case '*':
[150]55                                genformat = genstring.charAt(2);
56                                if ((end = genstring.indexOf("*/")) >= 0)
57                                {
58                                        newcomment = genstring.substr(2, end - 2);
59                                        gencopy = genstring.substr(end + 2);
60                                        mapinshift = end + 2;
61                                }
[109]62                                else
[150]63                                {
64                                        gencopy = 0;
65                                        mapinshift = genstring.len();
66                                }
[109]67                                break;
68                        }
[150]69                        if (newcomment.len() > 0)
[109]70                        {
[150]71                                SString token; int pos = 0;
72                                if (newcomment.getNextToken(pos, token, ';'))
73                                        if (newcomment.getNextToken(pos, token, ';'))
74                                        {
75                                                if (token.len()) txt = token;
76                                                if (newcomment.getNextToken(pos, token, ';'))
77                                                        if (token.len()) name = token;
78                                        }
[109]79                        }
80                }
81        }
82
[150]83        gen = gencopy;
84        format = genformat;
85        if (!name.len()) name = genname;
86        if (!txt.len()) txt = comment;
[348]87        multiline = (strchr(gen.c_str(), '\n') != 0);
[150]88        // mapoutshift...?
[109]89}
90
91void Geno::freeF0()
92{
[150]93        if (f0gen) { delete f0gen; f0gen = 0; }
[109]94}
95
[150]96Geno::Geno(const char *genstring, char genformat, const char *genname, const char *comment)
[109]97{
[150]98        init(SString(genstring), genformat, SString(genname), SString(comment));
[109]99}
100
[150]101Geno::Geno(const SString& genstring, char genformat, const SString& genname, const SString& comment)
[109]102{
[150]103        init(genstring, genformat, genname, comment);
[109]104}
105
106Geno::Geno(const Geno& src)
[150]107:gen(src.gen), name(src.name), format(src.format), txt(src.txt), isvalid(src.isvalid),
108f0gen(0), mapinshift(src.mapinshift), mapoutshift(src.mapinshift),
109multiline(src.multiline), owner(0)
110{
111        f0gen = src.f0gen ? new Geno(*src.f0gen) : 0; refcount = 1;
112}
[109]113
114void Geno::operator=(const Geno& src)
115{
[150]116        freeF0();
117        gen = src.gen;
118        name = src.name;
119        format = src.format;
120        txt = src.txt;
121        isvalid = src.isvalid;
122        mapinshift = src.mapinshift;
123        mapoutshift = src.mapinshift;
124        multiline = src.multiline;
125        f0gen = src.f0gen ? new Geno(*src.f0gen) : 0;
126        owner = 0;
[109]127}
128
129Geno::Geno(const SString& src)
130{
[150]131        init(src, -1, SString::empty(), SString::empty());
[109]132}
133
[150]134void Geno::setGene(const SString& g, char newformat)
[109]135{
[150]136        gen = g;
137        isvalid = -1;
138        freeF0();
139        if (newformat >= 0) format = newformat;
[109]140}
141
142void Geno::setString(const SString& g)
143{
[150]144        freeF0();
145        init(g, -1, SString::empty(), SString::empty());
[109]146}
147
148void Geno::setName(const SString& n)
149{
[150]150        name = n;
[109]151}
152
153void Geno::setComment(const SString& c)
154{
[150]155        txt = c;
[109]156}
157
158SString Geno::toString(void) const
159{
[150]160        SString out;
161        int comment = 0;
162        if ((format != '1') || (comment = (txt.len() || name.len())))
[109]163        {
[150]164                if (multiline)
165                        out += "//";
166                else
167                        out += "/*";
168                out += format;
169                if (comment)
[109]170                {
[150]171                        if (txt.len()) { out += ";"; out += txt; }
172                        if (name.len()){ out += ";"; out += name; }
[109]173                }
[150]174                if (multiline)
175                        out += "\n";
176                else
177                        out += "*/";
[109]178        }
[150]179        out += gen;
180        return out;
[109]181}
182
183SString Geno::shortString(void) const
184{
[150]185        SString out;
186        if (format != '1')
[109]187        {
[150]188                if (multiline)
189                        out += "//";
190                else
191                        out += "/*";
192                if (format == 0)
193                        out += "invalid";
194                else
195                        out += format;
196                if (multiline)
197                        out += "\n";
198                else
199                        out += "*/";
[109]200        }
[150]201        out += gen;
202        return out;
[109]203}
204
205int Geno::mapGenToString(int genpos) const
206{
[150]207        if (genpos > gen.len()) return -2;
208        if (genpos<0) return -1;
209        return mapinshift + genpos;
[109]210}
211
212int Geno::mapStringToGen(int stringpos) const
213{
[150]214        stringpos -= mapinshift;
215        if (stringpos>gen.len()) return -2;
216        if (stringpos < 0) return -1;
217        return stringpos;
[109]218}
219
[150]220SString Geno::getGene(void) const { return gen; }
221SString Geno::getName(void) const { return name; }
222char Geno::getFormat(void) const { return format; }
223SString Geno::getComment(void) const { return txt; }
[109]224
225int ModelGenoValidator::testGenoValidity(Geno& g)
226{
[150]227        if (g.getFormat() == '0')
[109]228        {
[150]229                Model mod(g);
230                return mod.isValid();
[109]231        }
[150]232        else
[109]233        {
[150]234                bool converter_missing;
235                Geno f0geno = g.getConverted('0', NULL, &converter_missing);
236                if (converter_missing)
237                        return -1;//no result
238                return f0geno.isValid();
[109]239        }
240}
241
242void Geno::validate()
243{
[150]244        if (isvalid >= 0) return;
245        if (gen.len() == 0) { isvalid = 0; return; }
[348]246        Validators* vals=getValidators();
247        if (vals!=NULL)
248                {
[508]249#ifdef WARN_VALIDATION_INCONSISTENCY
250                vector<int> results;
251                int first_result=-1;
252                FOREACH(GenoValidator*, v, (*vals))
253                        {
254                        int r=v->testGenoValidity(*this);
255                        if (first_result<0) first_result=r;
256                        results.push_back(r);
257                        }
258                int N=vals->size();
259                for(int i=1;i<N;i++)
260                        if (results[i]!=results[0])
261                                {
262                                SString txt="Inconsistent validation results";
263                                for(int i=0;i<N;i++)
264                                        txt+=SString::sprintf(" %d",results[i]);
265                                txt+=" for genotype '";
266                                txt+=getGene();
267                                txt+="'";
268                                logPrintf("Geno","validate",LOG_WARN,txt.c_str());
269                                break;
270                                }
271                isvalid=first_result;
272                if (isvalid>=0)
273                        return;
274#else
[348]275        FOREACH(GenoValidator*, v, (*vals))
[150]276                if ((isvalid = v->testGenoValidity(*this)) >= 0)
277                        return;
[508]278#endif
[348]279                }
[150]280        isvalid = 0;
[375]281        logPrintf("Geno", "validate", LOG_WARN, "Wrong configuration? No genotype validators defined for genetic format f%c.", format);
[109]282}
283
284bool Geno::isValid(void)
285{
[452]286        if (isvalid<0)
287                {
288                LoggerToMemory err(LoggerBase::Enable | LoggerToMemory::StoreAllMessages,LOG_INFO);
289                validate();
290                err.disable();
291                string msg=err.getCountSummary();
292                if (msg.size()>0)
293                        {
294                        msg+=ssprintf(" while checking validity of '%s'",getName().c_str());
295                        msg+="\n";
296                        msg+=err.getMessages();
297                        logMessage("Geno","isValid",err.getErrorLevel(),msg.c_str());
298                        }
299                }
[150]300        return isvalid>0;
[109]301}
302
[150]303Geno Geno::getConverted(char otherformat, MultiMap *m, bool *converter_missing)
[109]304{
[150]305        if (otherformat == getFormat()) { if (converter_missing) *converter_missing = false; return *this; }
[109]306#ifndef NO_GENOCONVMANAGER
[348]307        GenoConvManager *converters=getConverters();
[150]308        if (converters)
[109]309        {
[150]310                if ((otherformat == '0') && (!m))
[145]311                {
[150]312                        if (!f0gen)
313                                f0gen = new Geno(converters->convert(*this, otherformat, NULL, converter_missing));
[500]314                        else
315                                { if (converter_missing) *converter_missing = false; }
[150]316                        return *f0gen;
317                }
318                else
319                        return converters->convert(*this, otherformat, m, converter_missing);
[109]320        }
[145]321#endif
[150]322        if (converter_missing) *converter_missing = true;
323        return (otherformat == getFormat()) ? *this : Geno(0, 0, 0, "GenConvManager not available");
[109]324}
325
326Geno::~Geno()
327{
[150]328        if (f0gen) delete f0gen;
[109]329}
Note: See TracBrowser for help on using the repository browser.