Skip to content

Skew method limitations and areas of improvement #16

@brentwilder

Description

@brentwilder

Issue

There are tradeoffs between skew methods. Differences impact the horizon and therefore the net radiation via the terrain shadows. This minimally impacts sky view factor as well, although less so as n-angles increases.

Skew overview

The method skew() is called to rotate the image in order to compute horizons along a line for numpy array.

ARS Code

In the original ARS code, they defined it in this way,

def skew(arr, angle, fwd=True, fill_min=True):

    if angle == 0:
        return arr

    if angle > 45 or angle < -45:
        raise ValueError('skew angle must be between -45 and 45 degrees')

    nlines, nsamps = arr.shape

    if angle >= 0.0:
        negflag = False
    else:
        negflag = True
        angle = -angle

    slope = np.tan(angle * np.pi / 180.0)
    max_skew = int((nlines - 1) * slope + 0.5)

    o_nsamps = nsamps
    if fwd:
        o_nsamps += max_skew
    else:
        o_nsamps -= max_skew

    b = np.zeros((nlines, o_nsamps))
    if fill_min:
        b += np.min(arr)


    # NOTE , the critical piece for this issue is here:
    for line in range(nlines):
        o = line if negflag else nlines - line - 1
        offset = int(o * slope + 0.5)

        if fwd:
            b[line, offset:offset+nsamps] = arr[line, :]
        else:
            b[line, :] = arr[line, offset:offset+o_nsamps]

    return b

The offset is snapped via int, and so the result is that you end up with many streaking/lines in the data. However, the benefit of this approach, for there is no streaking is the values are exact ( no interpolation).

Image

Interpolation approach

In the more recent implementation created in, #12 and #14 , the last part of the method was changed to perform linear interpolation.

   # same code as above ....
    line_indices = np.arange(nlines)
    o_indices = line_indices if negflag else nlines - line_indices - 1
    offsets = o_indices * slope

    output_grid = np.arange(o_nsamps)
    source_grid = np.arange(nsamps)

    if fwd:
        for i in range(nlines):
            offset = offsets[i]
            source = output_grid - offset
            mask = (source >= 0) & (source <= nsamps - 1)
            y_k = np.interp(source[mask], source_grid, arr[i, :])
            b[i, mask] = y_k

    else:
        for i in range(nlines):
            offset = offsets[i]
            output = source_grid - offset
            mask = (output >= 0) & (output <= o_nsamps - 1)
            y_k = np.interp(output_grid, output[mask], arr[i, source_grid[mask]])
            b[i, :] = y_k

    return b
Image

However, this interpolation error manifests into a small bias for mostly shaded areas in early morning and late evening. This is because the horizon angles are smoothed out slightly. Which creates a small positive bias in net radiation.

Proposed solution?

  • Perhaps better interpolation strategy (cubic, or other?)

  • scipy.ndimage also has some tools for this but would require a new dependency. But could be worth testing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions