popmap.cpp 4.72 KB
Newer Older
RomainFeron's avatar
RomainFeron committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* Copyright (C) 2020 Romain Feron
* This file is part of RADSex.

* RADSex is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.

* RADSex is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with RADSex.  If not, see <https://www.gnu.org/licenses/>.
*/

19
20
21
22
23
/*!
 * @file popmap.cpp
 * @brief Implements the Popmap class.
*/

24
#include "popmap.h"
25
26


27
Popmap::Popmap(Parameters& parameters, bool check_groups) {
28

29
30
    this->file = parameters.popmap_file_path;
    std::ifstream popmap = open_input(this->file);
31

32
33
34
    std::string line;
    uint line_number = 1;
    std::vector<std::string> fields;
35

36
37
    // Parse popmap file
    while(std::getline(popmap, line)) {
38

39
40
        if (line.back() == '\r') line.pop_back();  // Deal with windows-style line endings
        fields = split(line, "\t");
41

42
        if (fields.size() == 2) { // Expected format: individual | group
43

44
45
46
            this->individual_groups[fields[0]] = fields[1];  // Store group for this individual
            ++this->group_counts[fields[1]];  // Increase count for this group
            ++this->n_individuals;  // Increase total individuals count
47

48
        } else {
49

50
            log("Could not process line " + std::to_string(line_number) + " in popmap file <" + this->file + "> (expected format: \"individual\tgroup\")", LOG_WARNING);
51

52
53
        }

54
        ++line_number;
55
56
57

    }

58
59
60
    if (check_groups) {

        if (this->group_counts.size() < 2) {  // Fewer than two groups in the popmap
61

62
63
            log("Found <" + std::to_string(this->group_counts.size()) + "> groups in the popmap file (" + this->print_groups() + ") but at least two are required", LOG_ERROR);
            exit(1);
64

65
        } else if (this->group_counts.size() > 2 and (parameters.group1 == "" or parameters.group2 == "")) {  // More than two groups but groups to compare were not defined
66

67
68
            log("Found <" + std::to_string(this->group_counts.size()) + "> groups in the popmap file (" + this->print_groups() + ") but groups to compare were not defined (use --groups group1,group2)", LOG_ERROR);
            exit(1);
69

70
        } else if (this->group_counts.size() > 2  and (this->group_counts.find(parameters.group1) == this->group_counts.end() or this->group_counts.find(parameters.group2) == this->group_counts.end())) {  // More than two groups and groups to compare were not found
71

72
73
            log("Groups specified with --groups (\"" + parameters.group1 + "\", \"" + parameters.group2 + "\") were not found in popmap groups (" + this->print_groups() + ")", LOG_ERROR);
            exit(1);
74

75
        } else if (this->group_counts.size() == 2) {  // Only two groups in popmap
76

77
            if (parameters.group1 == "" or parameters.group2 == "") {  // Fill groups from popmap if not specified by the user
78

79
80
81
                auto i = std::begin(this->group_counts);
                parameters.group1 = i->first;
                parameters.group2 = (++i)->first;
82

83
            }
84
        }
85

86
    }
87

88
    std::string popmap_success_message = "Loaded popmap (" + this->print_groups(true) + ")";
89
    log(popmap_success_message);
90
91
92
93
}



94
95


96
97
98
99
100
101
102
103
104
105
106
107
108
std::string Popmap::get_group(const std::string& individual) const {

    std::string group = "";

    if (this->individual_groups.find(individual) != this->individual_groups.end()) {

        group = this->individual_groups.at(individual);

    } else {

        log("Trying to get group for individual <" + individual + "> which was not found in popmap <" + this->file + ">", LOG_WARNING);

    }
109

110
    return group;
111
112
}

113
114


115
116


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
uint Popmap::get_count(const std::string& group) const {

    uint count = 0;

    if (this->group_counts.find(group) != this->group_counts.end()) {

        count = this->group_counts.at(group);

    } else {

        log("Trying to get individual count for group <" + group + "> which was not found in popmap <" + this->file + ">", LOG_WARNING);

    }

    return count;
}



136

137
138
139
140
141
142
143
144
145
146
147
std::vector<std::string> Popmap::get_groups() const {

    std::vector<std::string> groups;
    for (auto g: this->group_counts) groups.push_back(g.first);

    return groups;

}



148

149
std::string Popmap::print_groups(const bool counts) const {
150
151
152
153

    std::string list = "";
    uint n = 0;

154
155
    for (auto& group: this->group_counts) {

156
157
        list += "\"" + group.first + "\"";
        if (counts) list += ": " + std::to_string(group.second);
158
159
        if (++n < this->group_counts.size()) list += ", ";

160
161
162
163
    }

    return list;
}
164
165