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

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

Code formatting

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