File: Image.cpp

package info (click to toggle)
ausaxs 1.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 72,592 kB
  • sloc: cpp: 49,853; ansic: 6,901; python: 730; makefile: 18
file content (148 lines) | stat: -rw-r--r-- 4,944 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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
136
137
138
139
140
141
142
143
144
145
146
147
148
// SPDX-License-Identifier: LGPL-3.0-or-later
// Author: Kristian Lytje

#include <em/Image.h>
#include <em/detail/header/MapHeader.h>
#include <settings/EMSettings.h>
#include <utility/Axis3D.h>
#include <constants/Constants.h>
#include <hist/Histogram2D.h>

using namespace ausaxs;
using namespace ausaxs::em;

Image::Image(observer_ptr<em::detail::header::IMapHeader> header, unsigned int layer) : N(header->get_axes().x.bins), M(header->get_axes().y.bins), header(header), data(N, M), z(layer), bounds(N, M) {}

Image::Image(const Matrix<float>& data) : N(data.N), M(data.M), header(nullptr), data(data), z(0), bounds(N, M) {}

Image::Image(const Matrix<float>& data, observer_ptr<em::detail::header::IMapHeader> header, unsigned int layer) : N(data.N), M(data.M), header(header), data(data), z(layer), bounds(N, M) {}

const Matrix<float>& Image::get_data() const {
    return data;
}

void Image::set_z(unsigned int z) {this->z = z;}

unsigned int Image::get_z() const {return z;}

float Image::index(unsigned int x, unsigned int y) const {return data.index(x, y);}
float& Image::index(unsigned int x, unsigned int y) {return data.index(x, y);}

std::list<data::EMAtom> Image::generate_atoms(double cutoff) const {
    if (header == nullptr) [[unlikely]] {throw except::invalid_operation("Image::generate_atoms: Header must be initialized to use this method.");}
    std::list<data::EMAtom> atoms;
    auto map_axes = header->get_axes();

    // loop through all pixels in this image
    double xscale = map_axes.x.width();
    double yscale = map_axes.y.width();
    double zscale = map_axes.z.width();
    int step = static_cast<int>(settings::em::sample_frequency);
    
    // define a weight function for more efficient switching. 
    auto weight = settings::em::fixed_weights ? 
        [] (float) {return 1.0f;} :     // fixed weights enabled - all voxels have the same weight of 1
        [] (float val) {return val;}   // fixed weights disabled - voxels have a weight equal to their density
    ;

    for (int x = 0; x < static_cast<int>(N); x += step) {
        for (int y = static_cast<int>(bounds[x].min); y < static_cast<int>(bounds[x].max); y += step) {
            float val = index(x, y);
            if (val < cutoff) {continue;}
            atoms.emplace_back(Vector3<double>{x*xscale, y*yscale, z*zscale}, weight(val), val);
        }
    }
    return atoms;
}

unsigned int Image::count_voxels(double cutoff) const {
    unsigned int count = 0;
    int step = settings::em::sample_frequency;
    for (int x = 0; x < static_cast<int>(N); x += step) {
        for (int y = static_cast<int>(bounds[x].min); y < static_cast<int>(bounds[x].max); y += step) {
            if (index(x, y) >= cutoff) {
                count++;
            }
        }
    }
    return count;
}

double Image::squared_sum() const {
    double sum = 0;
    for (unsigned int x = 0; x < N; x++) {
        for (unsigned int y = 0; y < M; y++) {
            sum += std::pow(index(x, y), 2);
        }
    }
    return sum;
}

hist::Histogram2D Image::as_hist() const {
    if (header == nullptr) [[unlikely]] {throw except::invalid_operation("Image::as_hist: Header must be initialized to use this method.");}
    auto map_axes = header->get_axes();
    hist::Histogram2D hist(map_axes.x, map_axes.y);

    for (unsigned int x = 0; x < N; x++) {
        for (unsigned int y = 0; y < M; y++) {
            hist.data.index(x, y) = index(x, y);
        }
    }
    return hist;
}

double Image::mean() const {
    double sum = 0;
    for (unsigned int x = 0; x < N; x++) {
        for (unsigned int y = 0; y < M; y++) {
            sum += index(x, y);
        }
    }

    return sum/(N*M);
}

Limit Image::limits() const {
    double min = 1e9, max = -1e9;
    for (unsigned int x = 0; x < N; x++) {
        for (unsigned int y = 0; y < M; y++) {
            double val = index(x, y);
            min = std::min(min, val);
            max = std::max(max, val);
        }
    }

    return Limit(min, max);
}

void Image::set_header(observer_ptr<em::detail::header::IMapHeader> header) {
    this->header = header;
}

const ObjectBounds2D& Image::get_bounds() const {
    return bounds;
}

const ObjectBounds2D& Image::setup_bounds(double cutoff) {
    for (unsigned int x = 0; x < N; x++) {
        bounds.set_bounds(x, 0, 0);
        bool min_set = false;
        for (unsigned int y = 0; y < M; y++) {
            if (index(x, y) < cutoff) {continue;}
            if (!min_set) {
                bounds.set_bounds(x, y, y); // update min val to this index, and also set max in case this is the only entry
                min_set = true;
            } else {
                bounds.set_max(x, y);
            }
        }
    }

    return bounds;
}

bool Image::operator==(const Image& other) const {
    return data == other.data && N == other.N && M == other.M && z == other.z;
}

std::string Image::to_string() const {return data.to_string();}