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

Last change on this file since 732 was 732, checked in by Maciej Komosinski, 16 months ago

Added support for "checkpoints" (intermediate phases of development of the Model when converting between genetic encodings). See Model.checkpoint() and conv_f1.cpp for an example.

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