Commit ec544ea7 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Fix bug in histogram with bin list of size 2

This also changes the semantics of of bin list of size 2, and also
simplifies the histogram code slightly.
parent b311b048
......@@ -58,43 +58,38 @@ public:
bin_t new_shape;
for (size_t j = 0; j < Dim; ++j)
{
if (_bins[j].size() < 2)
throw std::range_error("invalid bin edge number < 2!");
if (_bins[j].size() < 1)
throw std::range_error("invalid bin edge number < 1!");
_data_range[j] = std::make_pair(0, 0);
// detect whether the given bins are of constant width, for faster
// binning
_const_width[j] = true;
value_type delta = _bins[j][1] - _bins[j][0];
for (size_t i = 2; i < _bins[j].size(); ++i)
if (_bins[j].size() == 2)
{
value_type d = _bins[j][i] - _bins[j][i-1];
if (delta != d)
_const_width[j] = false;
_data_range[j] = std::make_pair(_bins[j][0], _bins[j][0]);
delta = _bins[j][1];
_const_width[j] = true;
}
if (_const_width[j])
else
{
if (_bins[j].size() > 2)
// detect whether the given bins are of constant width, for faster
// binning
_const_width[j] = true;
for (size_t i = 2; i < _bins[j].size(); ++i)
{
_data_range[j] = std::make_pair(_bins[j].front(),
_bins[j].back());
new_shape[j] = _bins[j].size() - 1;
value_type d = _bins[j][i] - _bins[j][i-1];
if (delta != d)
_const_width[j] = false;
}
else
{
if (_const_width[j])
_data_range[j] = std::make_pair(_bins[j].front(),
_bins[j].front());
new_shape[j] = 1;
}
if (delta == 0)
throw std::range_error("invalid bin size of zero!");
}
else
{
new_shape[j] = _bins[j].size() - 1;
_bins[j].back());
}
if (delta == 0)
throw std::range_error("invalid bin size of zero!");
new_shape[j] = _bins[j].size() - 1;
}
_counts.resize(new_shape);
}
......@@ -106,11 +101,24 @@ public:
{
if (_const_width[i])
{
if (_data_range[i].first != _data_range[i].second &&
(v[i] < _data_range[i].first ||
v[i] > _data_range[i].second))
return; // out of bounds
value_type delta = _bins[i][1] - _bins[i][0];
value_type delta;
if (_data_range[i].first == _data_range[i].second)
{
delta = _bins[i][1];
if (v[i] < _data_range[i].first)
return; // out of bounds
}
else
{
delta = _bins[i][1] - _bins[i][0];
if (v[i] < _data_range[i].first ||
v[i] >= _data_range[i].second)
return; // out of bounds
}
bin[i] = (v[i] - _data_range[i].first) / delta;
if (bin[i] >= _counts.shape()[i]) // modify shape
{
......
......@@ -35,7 +35,7 @@ get_vertex_histogram(GraphInterface& gi, GraphInterface::deg_t deg,
run_action<>()(gi, get_histogram<VertexHistogramFiller>(hist, bins,
ret_bins),
scalar_selectors())(degree_selector(deg));
scalar_selectors())(degree_selector(deg));
return python::make_tuple(hist, ret_bins);
}
......
......@@ -35,7 +35,8 @@ class VertexHistogramFiller
{
public:
template <class Graph, class DegreeSelector, class Hist>
void operator()(Graph& g, typename graph_traits<Graph>::vertex_descriptor v,
void operator()(const Graph& g,
typename graph_traits<Graph>::vertex_descriptor v,
DegreeSelector& deg, Hist& hist)
{
typename Hist::point_t p;
......@@ -48,7 +49,8 @@ class EdgeHistogramFiller
{
public:
template <class Graph, class EdgeProperty, class Hist>
void operator()(Graph& g, typename graph_traits<Graph>::vertex_descriptor v,
void operator()(const Graph& g,
typename graph_traits<Graph>::vertex_descriptor v,
EdgeProperty& eprop, Hist& hist)
{
typename Hist::point_t p;
......@@ -71,7 +73,7 @@ struct get_histogram
: _hist(hist), _bins(bins), _ret_bins(ret_bins) {}
template <class Graph, class DegreeSelector>
void operator()(Graph& g, DegreeSelector deg) const
void operator()(const Graph& g, DegreeSelector deg) const
{
typedef typename DegreeSelector::value_type value_type;
typedef Histogram<value_type, size_t, 1> hist_t;
......
......@@ -211,10 +211,11 @@ def corr_hist(g, deg_source, deg_target, bins=[[0, 1], [0, 1]], weight=None,
deg_target : string or :class:`~graph_tool.PropertyMap`
degree type ("in", "out" or "total") or vertex property map for the
target vertex.
bins : list of lists (optional, default: [[1], [1]])
bins : list of lists (optional, default: [[0, 1], [0, 1]])
A list of bin edges to be used for the source and target degrees. If any
list has size 2, it is used as the constant width of an automatically
generated bin range, starting from the first value.
list has size 2, it is used to create an automatically generated bin
range starting from the first value, and with constant bin width given
by the second value.
weight : edge property map (optional, default: None)
Weight (multiplicative factor) to be used on each edge.
float_count : bool (optional, default: True)
......@@ -306,8 +307,9 @@ def combined_corr_hist(g, deg1, deg2, bins=[[0, 1], [0, 1]], float_count=True):
second degree type ("in", "out" or "total") or vertex property map.
bins : list of lists (optional, default: [[0, 1], [0, 1]])
A list of bin edges to be used for the first and second degrees. If any
list has size 2, it is used as the constant width of an automatically
generated bin range, starting from the first value.
list has size 2, it is used to create an automatically generated bin
range starting from the first value, and with constant bin width given
by the second value.
float_count : bool (optional, default: True)
If True, the bin counts are converted float variables, which is useful
for normalization, and other processing. It False, the bin counts will
......
......@@ -73,9 +73,9 @@ def vertex_hist(g, deg, bins=[0, 1], float_count=True):
bins : list of bins (optional, default: [0, 1])
List of bins to be used for the histogram. The values given represent
the edges of the bins (i.e. lower and upper bounds). If the list
contains two value, this will be used to automatically create an
appropriate bin range, with a constant lenght given by the difference of
the two values, and starting from the first value.
contains two values, this will be used to automatically create an
appropriate bin range, with a constant width given by the second value,
and starting from the first value.
float_count : bool (optional, default: True)
If True, the counts in each histogram bin will be returned as floats. If
False, they will be returned as integers.
......@@ -129,9 +129,9 @@ def edge_hist(g, eprop, bins=[0, 1], float_count=True):
bins : list of bins (optional, default: [0, 1])
List of bins to be used for the histogram. The values given represent
the edges of the bins (i.e. lower and upper bounds). If the list
contains two value, this will be used to automatically create an
appropriate bin range, with a constant lenght given by the difference of
the two values, and starting from the first value.
contains two values, this will be used to automatically create an
appropriate bin range, with a constant width given by the second value,
and starting from the first value.
float_count : bool (optional, default: True)
If True, the counts in each histogram bin will be returned as floats. If
False, they will be returned as integers.
......@@ -330,9 +330,9 @@ def distance_histogram(g, weight=None, bins=[0, 1], samples=None,
bins : list of bins (optional, default: [0, 1])
List of bins to be used for the histogram. The values given represent
the edges of the bins (i.e. lower and upper bounds). If the list
contains two value, this will be used to automatically create an
appropriate bin range, with a constant lenght given by the difference of
the two values, and starting from the first value.
contains two values, this will be used to automatically create an
appropriate bin range, with a constant width given by the second value,
and starting from the first value.
samples : int (optional, default: None)
If supplied, the distances will be randomly sampled from a number of
source vertices given by this parameter. It `samples == None` (default),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment