source: cpp/frams/genetics/genoconv.cpp

Last change on this file was 1256, checked in by Maciej Komosinski, 10 months ago
  • reasonable field names for enabling converters
  • automatically attach converter Param to GenoConvParam?
  • Property svn:eol-style set to native
File size: 5.6 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[1256]2// Copyright (C) 1999-2023  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[109]4
5#include <common/nonstd.h>
6
7#include <stdlib.h>
8#include <math.h>
9#include <stdio.h>
10#include <string.h>
11#include <ctype.h>
12#include <time.h>
13#include <errno.h>
14
15#include "genoconv.h"
16#include <frams/util/multimap.h>
[841]17#include <common/util-string.h>
[109]18
19///////////////////////////////////////////////////////////////////////////
20
[1183]21GenoConvParam::GenoConvParam(GenoConvManager *g) :Param(), gcm(g)
[109]22{
[150]23        updatetab();
[109]24}
25
26void GenoConvParam::freetab()
27{
[150]28        if (tab) free(tab);
29        tab = 0;
[109]30}
31
32const char *GenoConvParam::id(int i)
33{
[150]34        if (i >= gcm->converters.size()) return 0;
[1256]35        sprintf(tmp_id, "genoconv_%s", ((GenoConverter*)gcm->converters(i))->id().c_str());
[150]36        return tmp_id;
[109]37}
38
39void GenoConvParam::updatetab()
40{
[150]41        int i;
42        GenoConverter *gk;
43        ParamEntry *pe;
44        int ile = gcm->converters.size();
45        freetab();
46        tab = (ParamEntry*)calloc(2 + ile, sizeof(ParamEntry));
[1256]47        tab[0].id = "Genetics: Converters";
[150]48        tab[0].group = 1;
[483]49        tab[0].flags = (paInt)ile;
[150]50        tab[0].name = "gkparam:";
51        gcnames.clear();
[783]52        gcnames.reserve(gcm->converters.size()); //avoid reallocations in the loop below, since we externally store pointers to objects saved in this vector
[150]53        for (i = 0, pe = tab + 1; gk = (GenoConverter *)gcm->converters(i); pe++, i++)
[109]54        {
[150]55                pe->id = "?";
56                pe->group = 0;
57                pe->flags = 0;
58                std::string descr = "f";
[955]59                descr += gk->in_format.c_str();
[783]60                descr += " --> f";
[955]61                descr += gk->out_format.c_str();
[783]62                descr += "  :  ";
[150]63                descr += gk->name;
64                gcnames.push_back(descr);
[783]65                pe->name = gcnames.back().c_str(); //externally store a pointer to the object just saved in the vector
[150]66                pe->type = "d 0 1";
[109]67        }
[150]68        pe->id = 0;
[109]69}
70
71GenoConvParam::~GenoConvParam()
72{
[150]73        freetab();
[109]74}
75
76void *GenoConvParam::getTarget(int i)
77{
[150]78        GenoConverter *gk = (GenoConverter *)gcm->converters(i);
79        return &gk->enabled;
[109]80}
81
82GenoConvManager::GenoConvManager()
[1256]83        :conv_enabling_param(this),
84        param("GenoConverters", "Converters between genetic formats")
[109]85{
[1256]86        param += &conv_enabling_param;
[109]87}
88
89GenoConvManager::~GenoConvManager()
90{
[150]91        FOREACH(GenoConverter*, gc, converters) delete gc;
[109]92}
93
94void GenoConvManager::addConverter(GenoConverter *gc)
95{
[150]96        converters += gc;
[1256]97        auto *pi = gc->getParam();
98        if (pi)
99                param += pi;
100        conv_enabling_param.updatetab();
[109]101}
[1256]102
[109]103void GenoConvManager::removeConverter(GenoConverter *gc)
104{
[150]105        converters -= gc;
[1256]106        auto *pi = gc->getParam();
107        if (pi)
108                param -= pi;
109        conv_enabling_param.updatetab();
[109]110}
111
[955]112GenoConverter *GenoConvManager::findConverters(SListTempl<GenoConverter*>* result, const SString& in, const SString& out, int enabled, char* name)
[109]113{
[150]114        GenoConverter *gk, *retval = 0;
115        int i = 0;
116        for (; gk = (GenoConverter*)converters(i); i++)
[109]117        {
[988]118                if ((in != Geno::FORMAT_UNKNOWN) && (in != gk->in_format)) continue;
119                if ((out != Geno::FORMAT_UNKNOWN) && (out != gk->out_format)) continue;
[150]120                if ((enabled != -1) && (enabled != gk->enabled)) continue;
121                if ((name) && (strcmp(name, gk->name))) continue;
122                if (!retval) { retval = gk; if (!result) break; }
123                if (result) result->append(gk);
[109]124        }
[150]125        return retval;
[109]126}
127
[150]128/// Writes path into 'path'.
[109]129/// return the last path element (return >= path)
130/// null -> path not found
131/// @param mapavailable will receive 1 if conversion map is supported by all converters in path
132/// (can be NULL if you don't need this information)
133
[972]134GenoConverter **GenoConvManager::getPath(const SString& in_format, const SString& out_format_list, GenoConverter **path, int maxlen, int *mapavailable)
[109]135{
[150]136        if (!maxlen) return 0;
137        GenoConverter *gk;
138        int i = 0;
139        for (; gk = (GenoConverter*)converters(i); i++)
[109]140        {
[972]141                if ((gk->enabled) && (gk->in_format == in_format))
[109]142                {
[955]143                        *path = gk;
[972]144                        if (Geno::formatIsOneOf(gk->out_format, out_format_list))
[109]145                        {
[150]146                                if (mapavailable)
147                                        *mapavailable = gk->mapsupport;
148                                return path;
[109]149                        }
[150]150                        else
[109]151                        {
[150]152                                int mapavail;
[972]153                                GenoConverter **ret = getPath(gk->out_format, out_format_list, path + 1, maxlen - 1, &mapavail);
[150]154                                if (ret)
[109]155                                {
[150]156                                        if (mapavailable)
157                                                *mapavailable = gk->mapsupport && mapavail;
158                                        return ret;
[109]159                                }
160                        }
161                }
162        }
[150]163        return 0;
[109]164}
165
[972]166Geno GenoConvManager::convert(Geno &in, SString format_list, MultiMap *map, bool using_checkpoints, bool *converter_missing)
[109]167{
[972]168        if (Geno::formatIsOneOf(in.getFormat(), format_list))
169        {
[981]170                if (converter_missing) *converter_missing = false;
171                return in;
[972]172        }
[955]173        GenoConverter *path[10];
[150]174        int dep;
[955]175        GenoConverter **ret;
[981]176        if (in.isInvalid())
177        {
178                if (converter_missing) *converter_missing = false;
[988]179                return Geno("", Geno::FORMAT_INVALID, "", "Invalid genotype cannot be converted");
[981]180        }
[150]181        int mapavail;
182        for (dep = 1; dep < (int)sizeof(path); dep++) //iterative deepening
[972]183                if (ret = getPath(in.getFormat(), format_list, path, dep, &mapavail)) break;
[981]184        if (!ret)
185        {
186                if (converter_missing) *converter_missing = true;
[988]187                return Geno("", Geno::FORMAT_INVALID, "", "Converter not found");
[981]188        }
[150]189        if (converter_missing) *converter_missing = false;
190        if (!map) mapavail = 0;
[955]191        GenoConverter **t = path;
[972]192        SString tmp, out_format;
[534]193        tmp = in.getGenes();
[150]194        MultiMap lastmap, tmpmap;
195        int firstmap = 1;
196        for (; t <= ret; t++)
[109]197        {
[955]198                GenoConverter *gk = *t;
[732]199                tmp = gk->convert(tmp, mapavail ? &tmpmap : 0, using_checkpoints);
[972]200                out_format = gk->out_format;
201                if (!tmp.length())
[109]202                {
[955]203                        string t = ssprintf("f%s->f%s conversion failed (%s)", gk->in_format.c_str(), gk->out_format.c_str(), gk->name);
[988]204                        return Geno("", Geno::FORMAT_INVALID, "", t.c_str());
[109]205                }
[150]206                if (mapavail)
[109]207                {
[150]208                        if (firstmap)
[109]209                        {
[150]210                                lastmap = tmpmap;
211                                firstmap = 0;
[109]212                        }
[150]213                        else
[109]214                        {
[150]215                                MultiMap m;
216                                m.addCombined(lastmap, tmpmap);
217                                lastmap = m;
[109]218                        }
[150]219                        tmpmap.clear();
[109]220                }
221        }
[150]222        if (map)
223                *map = lastmap;
[972]224        return Geno(tmp, out_format, in.getName(), in.getComment());
[109]225}
Note: See TracBrowser for help on using the repository browser.