Skip to content

Commit

Permalink
Improved antialiased mean reduction
Browse files Browse the repository at this point in the history
  • Loading branch information
ianthomas23 authored and jbednar committed Oct 27, 2023
1 parent e247866 commit 23dfe67
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 46 deletions.
4 changes: 2 additions & 2 deletions datashader/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def get_cuda_mutex_call(lock: bool) -> str:

args.extend([local_lk[i] for i in temps])
if antialias:
args.append("aa_factor")
args += ["aa_factor", "prev_aa_factor"]

if local_cuda_mutex and prev_local_cuda_mutex:
# Avoid unnecessary mutex unlock and lock cycle
Expand Down Expand Up @@ -458,7 +458,7 @@ def get_cuda_mutex_call(lock: bool) -> str:
body = [get_cuda_mutex_call(True)] + body + [get_cuda_mutex_call(False)]

if antialias:
signature.insert(0, "aa_factor")
signature = ["aa_factor", "prev_aa_factor"] + signature

if ndims is None:
code = ('def append(x, y, {0}):\n'
Expand Down
2 changes: 1 addition & 1 deletion datashader/glyphs/glyph.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,6 @@ def _expand_aggs_and_cols(append, ndims, antialiased):

# Antialiased append() calls also take aa_factor argument
if antialiased:
aggs_and_cols_len -= 1
aggs_and_cols_len -= 2

return expand_varargs(aggs_and_cols_len)
7 changes: 5 additions & 2 deletions datashader/glyphs/line.py
Original file line number Diff line number Diff line change
Expand Up @@ -967,15 +967,18 @@ def _full_antialias(line_width, overwrite, i, x0, x1, y0, y1,
prev_correction = True
value = 1.0 - _linearstep(0.5*(line_width - aa), halfwidth, distance)
value *= scale
prev_value = 0.0
if prev_correction:
# Already set pixel from previous segment, need to correct it
prev_distance = abs((x-x0)*prev_rightx + (y-y0)*prev_righty)
prev_value = 1.0 - _linearstep(0.5*(line_width - aa), halfwidth, prev_distance)
prev_value *= scale
value = value - prev_value # Correction from previous segment.
if value <= prev_value:
# Have already used a larger value (alpha) for this pixel.
value = 0.0
if value > 0.0:
xx, yy = (y, x) if flip_xy else (x, y)
append(i, xx, yy, value, *aggs_and_cols)
append(i, xx, yy, value, prev_value, *aggs_and_cols)

return _full_antialias

Expand Down
99 changes: 64 additions & 35 deletions datashader/reductions.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,18 +556,18 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
if not isnull(field):
if isnull(agg[y, x]):
agg[y, x] = aa_factor
agg[y, x] = aa_factor - prev_aa_factor
else:
agg[y, x] += aa_factor
agg[y, x] += aa_factor - prev_aa_factor
return 0
return -1

@staticmethod
@ngjit
def _append_antialias_not_self_intersect(x, y, agg, field, aa_factor):
def _append_antialias_not_self_intersect(x, y, agg, field, aa_factor, prev_aa_factor):
if not isnull(field):
if isnull(agg[y, x]) or aa_factor > agg[y, x]:
agg[y, x] = aa_factor
Expand All @@ -582,16 +582,16 @@ def _append_no_field(x, y, agg):

@staticmethod
@ngjit
def _append_no_field_antialias(x, y, agg, aa_factor):
def _append_no_field_antialias(x, y, agg, aa_factor, prev_aa_factor):
if isnull(agg[y, x]):
agg[y, x] = aa_factor
agg[y, x] = aa_factor - prev_aa_factor
else:
agg[y, x] += aa_factor
agg[y, x] += aa_factor - prev_aa_factor
return 0

@staticmethod
@ngjit
def _append_no_field_antialias_not_self_intersect(x, y, agg, aa_factor):
def _append_no_field_antialias_not_self_intersect(x, y, agg, aa_factor, prev_aa_factor):
if isnull(agg[y, x]) or aa_factor > agg[y, x]:
agg[y, x] = aa_factor
return 0
Expand All @@ -600,7 +600,7 @@ def _append_no_field_antialias_not_self_intersect(x, y, agg, aa_factor):
# GPU append functions
@staticmethod
@nb_cuda.jit(device=True)
def _append_antialias_cuda(x, y, agg, field, aa_factor):
def _append_antialias_cuda(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value):
old = cuda_atomic_nanmax(agg, (y, x), value)
Expand All @@ -610,7 +610,7 @@ def _append_antialias_cuda(x, y, agg, field, aa_factor):

@staticmethod
@nb_cuda.jit(device=True)
def _append_no_field_antialias_cuda_not_self_intersect(x, y, agg, aa_factor):
def _append_no_field_antialias_cuda_not_self_intersect(x, y, agg, aa_factor, prev_aa_factor):
if not isnull(aa_factor):
old = cuda_atomic_nanmax(agg, (y, x), aa_factor)
if isnull(old) or old < aa_factor:
Expand All @@ -627,7 +627,7 @@ def _append_cuda(x, y, agg, field):

@staticmethod
@nb_cuda.jit(device=True)
def _append_no_field_antialias_cuda(x, y, agg, aa_factor):
def _append_no_field_antialias_cuda(x, y, agg, aa_factor, prev_aa_factor):
if not isnull(aa_factor):
old = cuda_atomic_nanmax(agg, (y, x), aa_factor)
if isnull(old) or old < aa_factor:
Expand Down Expand Up @@ -658,6 +658,35 @@ def _combine_antialias(aggs):
return ret


class _count_ignore_antialiasing(count):
"""Count reduction but ignores antialiasing. Used by mean reduction.
"""
def out_dshape(self, in_dshape, antialias, cuda, partitioned):
return dshape(ct.uint32)

def _antialias_stage_2(self, self_intersect, array_module) -> tuple[AntialiasStage2]:
if self_intersect:
return (AntialiasStage2(AntialiasCombination.SUM_1AGG, 0),)
else:
return (AntialiasStage2(AntialiasCombination.SUM_2AGG, 0),)

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
if not isnull(field) and prev_aa_factor == 0.0:
agg[y, x] += 1
return 0
return -1

@staticmethod
@ngjit
def _append_antialias_not_self_intersect(x, y, agg, field, aa_factor, prev_aa_factor):
if not isnull(field) and prev_aa_factor == 0.0:
agg[y, x] += 1
return 0
return -1


class by(Reduction):
"""Apply the provided reduction separately per category.
Expand Down Expand Up @@ -809,7 +838,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
if not isnull(field):
if isnull(agg[y, x]) or aa_factor > agg[y, x]:
agg[y, x] = aa_factor
Expand All @@ -824,7 +853,7 @@ def _append_no_field(x, y, agg):

@staticmethod
@ngjit
def _append_no_field_antialias(x, y, agg, aa_factor):
def _append_no_field_antialias(x, y, agg, aa_factor, prev_aa_factor):
if isnull(agg[y, x]) or aa_factor > agg[y, x]:
agg[y, x] = aa_factor
return 0
Expand Down Expand Up @@ -926,8 +955,8 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
value = field*aa_factor
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*(aa_factor - prev_aa_factor)
if not isnull(value):
# agg[y, x] cannot be null as initialised to zero.
agg[y, x] += value
Expand All @@ -936,7 +965,7 @@ def _append_antialias(x, y, agg, field, aa_factor):

@staticmethod
@ngjit
def _append_antialias_not_self_intersect(x, y, agg, field, aa_factor):
def _append_antialias_not_self_intersect(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value) and value > agg[y, x]:
# agg[y, x] cannot be null as initialised to zero.
Expand Down Expand Up @@ -1026,8 +1055,8 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
value = field*aa_factor
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*(aa_factor - prev_aa_factor)
if not isnull(value):
if isnull(agg[y, x]):
agg[y, x] = value
Expand All @@ -1038,7 +1067,7 @@ def _append_antialias(x, y, agg, field, aa_factor):

@staticmethod
@ngjit
def _append_antialias_not_self_intersect(x, y, agg, field, aa_factor):
def _append_antialias_not_self_intersect(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value):
if isnull(agg[y, x]) or value > agg[y, x]:
Expand Down Expand Up @@ -1145,7 +1174,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value) and (isnull(agg[y, x]) or value > agg[y, x]):
agg[y, x] = value
Expand Down Expand Up @@ -1190,7 +1219,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value) and (isnull(agg[y, x]) or value > agg[y, x]):
agg[y, x] = value
Expand All @@ -1200,7 +1229,7 @@ def _append_antialias(x, y, agg, field, aa_factor):
# GPU append functions
@staticmethod
@nb_cuda.jit(device=True)
def _append_antialias_cuda(x, y, agg, field, aa_factor):
def _append_antialias_cuda(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value):
old = cuda_atomic_nanmax(agg, (y, x), value)
Expand Down Expand Up @@ -1247,7 +1276,7 @@ class mean(Reduction):
``NaN`` values in the column are skipped.
"""
def _build_bases(self, cuda, partitioned):
return (_sum_zero(self.column), count(self.column))
return (_sum_zero(self.column), _count_ignore_antialiasing(self.column))

@staticmethod
def _finalize(bases, cuda=False, **kwargs):
Expand Down Expand Up @@ -1365,7 +1394,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value) and (isnull(agg[y, x]) or value > agg[y, x]):
agg[y, x] = value
Expand Down Expand Up @@ -1403,7 +1432,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value) and (isnull(agg[y, x]) or value > agg[y, x]):
agg[y, x] = value
Expand Down Expand Up @@ -1512,7 +1541,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value):
# Check final value first for quick abort.
Expand Down Expand Up @@ -1549,7 +1578,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value):
# Always inserts at front of agg's third dimension.
Expand Down Expand Up @@ -1584,7 +1613,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value):
# Linear walk along stored values.
Expand Down Expand Up @@ -1664,7 +1693,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
value = field*aa_factor
if not isnull(value):
# Linear walk along stored values.
Expand Down Expand Up @@ -1841,7 +1870,7 @@ def _append(x, y, agg, field, update_index):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor, update_index):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor, update_index):
# Ignore aa_factor.
if agg.ndim > 2:
shift_and_insert(agg[y, x], field, update_index)
Expand All @@ -1850,7 +1879,7 @@ def _append_antialias(x, y, agg, field, aa_factor, update_index):

@staticmethod
@nb_cuda.jit(device=True)
def _append_antialias_cuda(x, y, agg, field, aa_factor, update_index):
def _append_antialias_cuda(x, y, agg, field, aa_factor, prev_aa_factor, update_index):
# Ignore aa_factor
if agg.ndim > 2:
cuda_shift_and_insert(agg[y, x], field, update_index)
Expand Down Expand Up @@ -2172,7 +2201,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
# field is int64 row index
# Ignore aa_factor
if field > agg[y, x]:
Expand Down Expand Up @@ -2230,7 +2259,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
# field is int64 row index
# Ignore aa_factor
if field != -1 and (agg[y, x] == -1 or field < agg[y, x]):
Expand Down Expand Up @@ -2326,7 +2355,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
# field is int64 row index
# Ignoring aa_factor
if field != -1:
Expand Down Expand Up @@ -2409,7 +2438,7 @@ def _append(x, y, agg, field):

@staticmethod
@ngjit
def _append_antialias(x, y, agg, field, aa_factor):
def _append_antialias(x, y, agg, field, aa_factor, prev_aa_factor):
# field is int64 row index
# Ignoring aa_factor
if field != -1:
Expand Down
Loading

0 comments on commit 23dfe67

Please sign in to comment.