signature:
def noise4d ( self , x , y , z , w ) :
    """Generate 4D OpenSimplex noise from X , Y , Z , W coordinates ."""

implementation:
# Place input coordinates on simplectic honeycomb .
stretch_offset = ( x + y + z + w ) * STRETCH_CONSTANT_4D
xs = x + stretch_offset
ys = y + stretch_offset
zs = z + stretch_offset
ws = w + stretch_offset
# Floor to get simplectic honeycomb coordinates of rhombo - hypercube super - cell origin .
xsb = floor ( xs )
ysb = floor ( ys )
zsb = floor ( zs )
wsb = floor ( ws )
# Skew out to get actual coordinates of stretched rhombo - hypercube origin . We ' ll need these later .
squish_offset = ( xsb + ysb + zsb + wsb ) * SQUISH_CONSTANT_4D
xb = xsb + squish_offset
yb = ysb + squish_offset
zb = zsb + squish_offset
wb = wsb + squish_offset
# Compute simplectic honeycomb coordinates relative to rhombo - hypercube origin .
xins = xs - xsb
yins = ys - ysb
zins = zs - zsb
wins = ws - wsb
# Sum those together to get a value that determines which region we ' re in .
in_sum = xins + yins + zins + wins
# Positions relative to origin po .
dx0 = x - xb
dy0 = y - yb
dz0 = z - zb
dw0 = w - wb
value = 0
extrapolate = self . _extrapolate4d
if in_sum <= 1 : # We ' re inside the pentachoron ( 4 - Simplex ) at ( 0,0,0,0)
# Determine which two of ( 0,0,0,1 ) , ( 0,0,1,0 ) , ( 0,1,0,0 ) , ( 1,0,0,0 ) are closest .
    a_po = 0x01
    a_score = xins
    b_po = 0x02
    b_score = yins
    if a_score >= b_score and zins > b_score :
        b_score = zins
        b_po = 0x04
    elif a_score < b_score and zins > a_score :
        a_score = zins
        a_po = 0x04
    if a_score >= b_score and wins > b_score :
        b_score = wins
        b_po = 0x08
    elif a_score < b_score and wins > a_score :
        a_score = wins
        a_po = 0x08
    # Now we determine the three lattice pos not part of the pentachoron that may contribute .
    # This depends on the closest two pentachoron vertices , including ( 0,0,0,0)
    uins = 1 - in_sum
    if uins > a_score or uins > b_score : # (0,0,0,0 ) is one of the closest two pentachoron vertices .
        c = b_po if ( b_score > a_score ) else a_po
        # Our other closest vertex is the closest out of a and b .
        if ( c & 0x01 ) == 0 :
            xsv_ext0 = xsb - 1
            xsv_ext1 = xsv_ext2 = xsb
            dx_ext0 = dx0 + 1
            dx_ext1 = dx_ext2 = dx0
        else :
            xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1
            dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 1
        if ( c & 0x02 ) == 0 :
            ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb
            dy_ext0 = dy_ext1 = dy_ext2 = dy0
            if ( c & 0x01 ) == 0x01 :
                ysv_ext0 -= 1
                dy_ext0 += 1
            else :
                ysv_ext1 -= 1
                dy_ext1 += 1
        else :
            ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1
            dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1
        if ( c & 0x04 ) == 0 :
            zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb
            dz_ext0 = dz_ext1 = dz_ext2 = dz0
            if ( c & 0x03 ) != 0 :
                if ( c & 0x03 ) == 0x03 :
                    zsv_ext0 -= 1
                    dz_ext0 += 1
                else :
                    zsv_ext1 -= 1
                    dz_ext1 += 1
            else :
                zsv_ext2 -= 1
                dz_ext2 += 1
        else :
            zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1
            dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1
        if ( c & 0x08 ) == 0 :
            wsv_ext0 = wsv_ext1 = wsb
            wsv_ext2 = wsb - 1
            dw_ext0 = dw_ext1 = dw0
            dw_ext2 = dw0 + 1
        else :
            wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1
            dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 1
    else : # (0,0,0,0 ) is not one of the closest two pentachoron vertices .
        c = ( a_po | b_po )
        # Our three extra vertices are determined by the closest two .
        if ( c & 0x01 ) == 0 :
            xsv_ext0 = xsv_ext2 = xsb
            xsv_ext1 = xsb - 1
            dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D
            dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_4D
            dx_ext2 = dx0 - SQUISH_CONSTANT_4D
        else :
            xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1
            dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
            dx_ext1 = dx_ext2 = dx0 - 1 - SQUISH_CONSTANT_4D
        if ( c & 0x02 ) == 0 :
            ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb
            dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D
            dy_ext1 = dy_ext2 = dy0 - SQUISH_CONSTANT_4D
            if ( c & 0x01 ) == 0x01 :
                ysv_ext1 -= 1
                dy_ext1 += 1
            else :
                ysv_ext2 -= 1
                dy_ext2 += 1
        else :
            ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1
            dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
            dy_ext1 = dy_ext2 = dy0 - 1 - SQUISH_CONSTANT_4D
        if ( c & 0x04 ) == 0 :
            zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb
            dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D
            dz_ext1 = dz_ext2 = dz0 - SQUISH_CONSTANT_4D
            if ( c & 0x03 ) == 0x03 :
                zsv_ext1 -= 1
                dz_ext1 += 1
            else :
                zsv_ext2 -= 1
                dz_ext2 += 1
        else :
            zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1
            dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
            dz_ext1 = dz_ext2 = dz0 - 1 - SQUISH_CONSTANT_4D
        if ( c & 0x08 ) == 0 :
            wsv_ext0 = wsv_ext1 = wsb
            wsv_ext2 = wsb - 1
            dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D
            dw_ext1 = dw0 - SQUISH_CONSTANT_4D
            dw_ext2 = dw0 + 1 - SQUISH_CONSTANT_4D
        else :
            wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1
            dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
            dw_ext1 = dw_ext2 = dw0 - 1 - SQUISH_CONSTANT_4D
    # Contribution ( 0,0,0,0)
    attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0
    if attn0 > 0 :
        attn0 *= attn0
        value += attn0 * attn0 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 0 , wsb + 0 , dx0 , dy0 , dz0 , dw0 )
    # Contribution ( 1,0,0,0)
    dx1 = dx0 - 1 - SQUISH_CONSTANT_4D
    dy1 = dy0 - 0 - SQUISH_CONSTANT_4D
    dz1 = dz0 - 0 - SQUISH_CONSTANT_4D
    dw1 = dw0 - 0 - SQUISH_CONSTANT_4D
    attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1
    if attn1 > 0 :
        attn1 *= attn1
        value += attn1 * attn1 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 0 , wsb + 0 , dx1 , dy1 , dz1 , dw1 )
    # Contribution ( 0,1,0,0)
    dx2 = dx0 - 0 - SQUISH_CONSTANT_4D
    dy2 = dy0 - 1 - SQUISH_CONSTANT_4D
    dz2 = dz1
    dw2 = dw1
    attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2
    if attn2 > 0 :
        attn2 *= attn2
        value += attn2 * attn2 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 0 , wsb + 0 , dx2 , dy2 , dz2 , dw2 )
    # Contribution ( 0,0,1,0)
    dx3 = dx2
    dy3 = dy1
    dz3 = dz0 - 1 - SQUISH_CONSTANT_4D
    dw3 = dw1
    attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3
    if attn3 > 0 :
        attn3 *= attn3
        value += attn3 * attn3 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 1 , wsb + 0 , dx3 , dy3 , dz3 , dw3 )
    # Contribution ( 0,0,0,1)
    dx4 = dx2
    dy4 = dy1
    dz4 = dz1
    dw4 = dw0 - 1 - SQUISH_CONSTANT_4D
    attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4
    if attn4 > 0 :
        attn4 *= attn4
        value += attn4 * attn4 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 0 , wsb + 1 , dx4 , dy4 , dz4 , dw4 )
elif in_sum >= 3 : # We ' re inside the pentachoron ( 4 - Simplex ) at ( 1,1,1,1)
# Determine which two of ( 1,1,1,0 ) , ( 1,1,0,1 ) , ( 1,0,1,1 ) , ( 0,1,1,1 ) are closest .
    a_po = 0x0E
    a_score = xins
    b_po = 0x0D
    b_score = yins
    if a_score <= b_score and zins < b_score :
        b_score = zins
        b_po = 0x0B
    elif a_score > b_score and zins < a_score :
        a_score = zins
        a_po = 0x0B
    if a_score <= b_score and wins < b_score :
        b_score = wins
        b_po = 0x07
    elif a_score > b_score and wins < a_score :
        a_score = wins
        a_po = 0x07
    # Now we determine the three lattice pos not part of the pentachoron that may contribute .
    # This depends on the closest two pentachoron vertices , including ( 0,0,0,0)
    uins = 4 - in_sum
    if uins < a_score or uins < b_score : # (1,1,1,1 ) is one of the closest two pentachoron vertices .
        c = b_po if ( b_score < a_score ) else a_po
        # Our other closest vertex is the closest out of a and b .
        if ( c & 0x01 ) != 0 :
            xsv_ext0 = xsb + 2
            xsv_ext1 = xsv_ext2 = xsb + 1
            dx_ext0 = dx0 - 2 - 4 * SQUISH_CONSTANT_4D
            dx_ext1 = dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D
        else :
            xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb
            dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 4 * SQUISH_CONSTANT_4D
        if ( c & 0x02 ) != 0 :
            ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1
            dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D
            if ( c & 0x01 ) != 0 :
                ysv_ext1 += 1
                dy_ext1 -= 1
            else :
                ysv_ext0 += 1
                dy_ext0 -= 1
        else :
            ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb
            dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 4 * SQUISH_CONSTANT_4D
        if ( c & 0x04 ) != 0 :
            zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1
            dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D
            if ( c & 0x03 ) != 0x03 :
                if ( c & 0x03 ) == 0 :
                    zsv_ext0 += 1
                    dz_ext0 -= 1
                else :
                    zsv_ext1 += 1
                    dz_ext1 -= 1
            else :
                zsv_ext2 += 1
                dz_ext2 -= 1
        else :
            zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb
            dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 4 * SQUISH_CONSTANT_4D
        if ( c & 0x08 ) != 0 :
            wsv_ext0 = wsv_ext1 = wsb + 1
            wsv_ext2 = wsb + 2
            dw_ext0 = dw_ext1 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D
            dw_ext2 = dw0 - 2 - 4 * SQUISH_CONSTANT_4D
        else :
            wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb
            dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 4 * SQUISH_CONSTANT_4D
    else : # (1,1,1,1 ) is not one of the closest two pentachoron vertices .
        c = ( a_po & b_po )
        # Our three extra vertices are determined by the closest two .
        if ( c & 0x01 ) != 0 :
            xsv_ext0 = xsv_ext2 = xsb + 1
            xsv_ext1 = xsb + 2
            dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
            dx_ext1 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D
            dx_ext2 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D
        else :
            xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb
            dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D
            dx_ext1 = dx_ext2 = dx0 - 3 * SQUISH_CONSTANT_4D
        if ( c & 0x02 ) != 0 :
            ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1
            dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
            dy_ext1 = dy_ext2 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D
            if ( c & 0x01 ) != 0 :
                ysv_ext2 += 1
                dy_ext2 -= 1
            else :
                ysv_ext1 += 1
                dy_ext1 -= 1
        else :
            ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb
            dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D
            dy_ext1 = dy_ext2 = dy0 - 3 * SQUISH_CONSTANT_4D
        if ( c & 0x04 ) != 0 :
            zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1
            dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
            dz_ext1 = dz_ext2 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D
            if ( c & 0x03 ) != 0 :
                zsv_ext2 += 1
                dz_ext2 -= 1
            else :
                zsv_ext1 += 1
                dz_ext1 -= 1
        else :
            zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb
            dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D
            dz_ext1 = dz_ext2 = dz0 - 3 * SQUISH_CONSTANT_4D
        if ( c & 0x08 ) != 0 :
            wsv_ext0 = wsv_ext1 = wsb + 1
            wsv_ext2 = wsb + 2
            dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
            dw_ext1 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D
            dw_ext2 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D
        else :
            wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb
            dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D
            dw_ext1 = dw_ext2 = dw0 - 3 * SQUISH_CONSTANT_4D
    # Contribution ( 1,1,1,0)
    dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D
    dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D
    dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D
    dw4 = dw0 - 3 * SQUISH_CONSTANT_4D
    attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4
    if attn4 > 0 :
        attn4 *= attn4
        value += attn4 * attn4 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 1 , wsb + 0 , dx4 , dy4 , dz4 , dw4 )
    # Contribution ( 1,1,0,1)
    dx3 = dx4
    dy3 = dy4
    dz3 = dz0 - 3 * SQUISH_CONSTANT_4D
    dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D
    attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3
    if attn3 > 0 :
        attn3 *= attn3
        value += attn3 * attn3 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 0 , wsb + 1 , dx3 , dy3 , dz3 , dw3 )
    # Contribution ( 1,0,1,1)
    dx2 = dx4
    dy2 = dy0 - 3 * SQUISH_CONSTANT_4D
    dz2 = dz4
    dw2 = dw3
    attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2
    if attn2 > 0 :
        attn2 *= attn2
        value += attn2 * attn2 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 1 , wsb + 1 , dx2 , dy2 , dz2 , dw2 )
    # Contribution ( 0,1,1,1)
    dx1 = dx0 - 3 * SQUISH_CONSTANT_4D
    dz1 = dz4
    dy1 = dy4
    dw1 = dw3
    attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1
    if attn1 > 0 :
        attn1 *= attn1
        value += attn1 * attn1 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 1 , wsb + 1 , dx1 , dy1 , dz1 , dw1 )
    # Contribution ( 1,1,1,1)
    dx0 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D
    dy0 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D
    dz0 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D
    dw0 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D
    attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0
    if attn0 > 0 :
        attn0 *= attn0
        value += attn0 * attn0 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 1 , wsb + 1 , dx0 , dy0 , dz0 , dw0 )
elif in_sum <= 2 : # We ' re inside the first dispentachoron ( Rectified 4 - Simplex )
    a_is_bigger_side = True
    b_is_bigger_side = True
    # Decide between ( 1,1,0,0 ) and ( 0,0,1,1)
    if xins + yins > zins + wins :
        a_score = xins + yins
        a_po = 0x03
    else :
        a_score = zins + wins
        a_po = 0x0C
    # Decide between ( 1,0,1,0 ) and ( 0,1,0,1)
    if xins + zins > yins + wins :
        b_score = xins + zins
        b_po = 0x05
    else :
        b_score = yins + wins
        b_po = 0x0A
    # Closer between ( 1,0,0,1 ) and ( 0,1,1,0 ) will replace the further of a and b , if closer .
    if xins + wins > yins + zins :
        score = xins + wins
        if a_score >= b_score and score > b_score :
            b_score = score
            b_po = 0x09
        elif a_score < b_score and score > a_score :
            a_score = score
            a_po = 0x09
    else :
        score = yins + zins
        if a_score >= b_score and score > b_score :
            b_score = score
            b_po = 0x06
        elif a_score < b_score and score > a_score :
            a_score = score
            a_po = 0x06
    # Decide if ( 1,0,0,0 ) is closer .
    p1 = 2 - in_sum + xins
    if a_score >= b_score and p1 > b_score :
        b_score = p1
        b_po = 0x01
        b_is_bigger_side = False
    elif a_score < b_score and p1 > a_score :
        a_score = p1
        a_po = 0x01
        a_is_bigger_side = False
    # Decide if ( 0,1,0,0 ) is closer .
    p2 = 2 - in_sum + yins
    if a_score >= b_score and p2 > b_score :
        b_score = p2
        b_po = 0x02
        b_is_bigger_side = False
    elif a_score < b_score and p2 > a_score :
        a_score = p2
        a_po = 0x02
        a_is_bigger_side = False
    # Decide if ( 0,0,1,0 ) is closer .
    p3 = 2 - in_sum + zins
    if a_score >= b_score and p3 > b_score :
        b_score = p3
        b_po = 0x04
        b_is_bigger_side = False
    elif a_score < b_score and p3 > a_score :
        a_score = p3
        a_po = 0x04
        a_is_bigger_side = False
    # Decide if ( 0,0,0,1 ) is closer .
    p4 = 2 - in_sum + wins
    if a_score >= b_score and p4 > b_score :
        b_po = 0x08
        b_is_bigger_side = False
    elif a_score < b_score and p4 > a_score :
        a_po = 0x08
        a_is_bigger_side = False
    # Where each of the two closest pos are determines how the extra three vertices are calculated .
    if a_is_bigger_side == b_is_bigger_side :
        if a_is_bigger_side : # Both closest pos on the bigger side
            c1 = ( a_po | b_po )
            c2 = ( a_po & b_po )
            if ( c1 & 0x01 ) == 0 :
                xsv_ext0 = xsb
                xsv_ext1 = xsb - 1
                dx_ext0 = dx0 - 3 * SQUISH_CONSTANT_4D
                dx_ext1 = dx0 + 1 - 2 * SQUISH_CONSTANT_4D
            else :
                xsv_ext0 = xsv_ext1 = xsb + 1
                dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D
                dx_ext1 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
            if ( c1 & 0x02 ) == 0 :
                ysv_ext0 = ysb
                ysv_ext1 = ysb - 1
                dy_ext0 = dy0 - 3 * SQUISH_CONSTANT_4D
                dy_ext1 = dy0 + 1 - 2 * SQUISH_CONSTANT_4D
            else :
                ysv_ext0 = ysv_ext1 = ysb + 1
                dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D
                dy_ext1 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
            if ( c1 & 0x04 ) == 0 :
                zsv_ext0 = zsb
                zsv_ext1 = zsb - 1
                dz_ext0 = dz0 - 3 * SQUISH_CONSTANT_4D
                dz_ext1 = dz0 + 1 - 2 * SQUISH_CONSTANT_4D
            else :
                zsv_ext0 = zsv_ext1 = zsb + 1
                dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D
                dz_ext1 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
            if ( c1 & 0x08 ) == 0 :
                wsv_ext0 = wsb
                wsv_ext1 = wsb - 1
                dw_ext0 = dw0 - 3 * SQUISH_CONSTANT_4D
                dw_ext1 = dw0 + 1 - 2 * SQUISH_CONSTANT_4D
            else :
                wsv_ext0 = wsv_ext1 = wsb + 1
                dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D
                dw_ext1 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
            # One combination is a _ permutation of ( 0,0,0,2 ) based on c2
            xsv_ext2 = xsb
            ysv_ext2 = ysb
            zsv_ext2 = zsb
            wsv_ext2 = wsb
            dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D
            dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D
            dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D
            dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D
            if ( c2 & 0x01 ) != 0 :
                xsv_ext2 += 2
                dx_ext2 -= 2
            elif ( c2 & 0x02 ) != 0 :
                ysv_ext2 += 2
                dy_ext2 -= 2
            elif ( c2 & 0x04 ) != 0 :
                zsv_ext2 += 2
                dz_ext2 -= 2
            else :
                wsv_ext2 += 2
                dw_ext2 -= 2
        else : # Both closest pos on the smaller side
        # One of the two extra pos is ( 0,0,0,0)
            xsv_ext2 = xsb
            ysv_ext2 = ysb
            zsv_ext2 = zsb
            wsv_ext2 = wsb
            dx_ext2 = dx0
            dy_ext2 = dy0
            dz_ext2 = dz0
            dw_ext2 = dw0
            # Other two pos are based on the omitted axes .
            c = ( a_po | b_po )
            if ( c & 0x01 ) == 0 :
                xsv_ext0 = xsb - 1
                xsv_ext1 = xsb
                dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D
                dx_ext1 = dx0 - SQUISH_CONSTANT_4D
            else :
                xsv_ext0 = xsv_ext1 = xsb + 1
                dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D
            if ( c & 0x02 ) == 0 :
                ysv_ext0 = ysv_ext1 = ysb
                dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D
                if ( c & 0x01 ) == 0x01 :
                    ysv_ext0 -= 1
                    dy_ext0 += 1
                else :
                    ysv_ext1 -= 1
                    dy_ext1 += 1
            else :
                ysv_ext0 = ysv_ext1 = ysb + 1
                dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D
            if ( c & 0x04 ) == 0 :
                zsv_ext0 = zsv_ext1 = zsb
                dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D
                if ( c & 0x03 ) == 0x03 :
                    zsv_ext0 -= 1
                    dz_ext0 += 1
                else :
                    zsv_ext1 -= 1
                    dz_ext1 += 1
            else :
                zsv_ext0 = zsv_ext1 = zsb + 1
                dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D
            if ( c & 0x08 ) == 0 :
                wsv_ext0 = wsb
                wsv_ext1 = wsb - 1
                dw_ext0 = dw0 - SQUISH_CONSTANT_4D
                dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D
            else :
                wsv_ext0 = wsv_ext1 = wsb + 1
                dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D
    else : # One po on each " side "
        if a_is_bigger_side :
            c1 = a_po
            c2 = b_po
        else :
            c1 = b_po
            c2 = a_po
        # Two contributions are the bigger - sided po with each 0 replaced with - 1.
        if ( c1 & 0x01 ) == 0 :
            xsv_ext0 = xsb - 1
            xsv_ext1 = xsb
            dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D
            dx_ext1 = dx0 - SQUISH_CONSTANT_4D
        else :
            xsv_ext0 = xsv_ext1 = xsb + 1
            dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D
        if ( c1 & 0x02 ) == 0 :
            ysv_ext0 = ysv_ext1 = ysb
            dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D
            if ( c1 & 0x01 ) == 0x01 :
                ysv_ext0 -= 1
                dy_ext0 += 1
            else :
                ysv_ext1 -= 1
                dy_ext1 += 1
        else :
            ysv_ext0 = ysv_ext1 = ysb + 1
            dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D
        if ( c1 & 0x04 ) == 0 :
            zsv_ext0 = zsv_ext1 = zsb
            dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D
            if ( c1 & 0x03 ) == 0x03 :
                zsv_ext0 -= 1
                dz_ext0 += 1
            else :
                zsv_ext1 -= 1
                dz_ext1 += 1
        else :
            zsv_ext0 = zsv_ext1 = zsb + 1
            dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D
        if ( c1 & 0x08 ) == 0 :
            wsv_ext0 = wsb
            wsv_ext1 = wsb - 1
            dw_ext0 = dw0 - SQUISH_CONSTANT_4D
            dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D
        else :
            wsv_ext0 = wsv_ext1 = wsb + 1
            dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D
        # One contribution is a _ permutation of ( 0,0,0,2 ) based on the smaller - sided po
        xsv_ext2 = xsb
        ysv_ext2 = ysb
        zsv_ext2 = zsb
        wsv_ext2 = wsb
        dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D
        dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D
        dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D
        dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D
        if ( c2 & 0x01 ) != 0 :
            xsv_ext2 += 2
            dx_ext2 -= 2
        elif ( c2 & 0x02 ) != 0 :
            ysv_ext2 += 2
            dy_ext2 -= 2
        elif ( c2 & 0x04 ) != 0 :
            zsv_ext2 += 2
            dz_ext2 -= 2
        else :
            wsv_ext2 += 2
            dw_ext2 -= 2
    # Contribution ( 1,0,0,0)
    dx1 = dx0 - 1 - SQUISH_CONSTANT_4D
    dy1 = dy0 - 0 - SQUISH_CONSTANT_4D
    dz1 = dz0 - 0 - SQUISH_CONSTANT_4D
    dw1 = dw0 - 0 - SQUISH_CONSTANT_4D
    attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1
    if attn1 > 0 :
        attn1 *= attn1
        value += attn1 * attn1 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 0 , wsb + 0 , dx1 , dy1 , dz1 , dw1 )
    # Contribution ( 0,1,0,0)
    dx2 = dx0 - 0 - SQUISH_CONSTANT_4D
    dy2 = dy0 - 1 - SQUISH_CONSTANT_4D
    dz2 = dz1
    dw2 = dw1
    attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2
    if attn2 > 0 :
        attn2 *= attn2
        value += attn2 * attn2 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 0 , wsb + 0 , dx2 , dy2 , dz2 , dw2 )
    # Contribution ( 0,0,1,0)
    dx3 = dx2
    dy3 = dy1
    dz3 = dz0 - 1 - SQUISH_CONSTANT_4D
    dw3 = dw1
    attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3
    if attn3 > 0 :
        attn3 *= attn3
        value += attn3 * attn3 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 1 , wsb + 0 , dx3 , dy3 , dz3 , dw3 )
    # Contribution ( 0,0,0,1)
    dx4 = dx2
    dy4 = dy1
    dz4 = dz1
    dw4 = dw0 - 1 - SQUISH_CONSTANT_4D
    attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4
    if attn4 > 0 :
        attn4 *= attn4
        value += attn4 * attn4 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 0 , wsb + 1 , dx4 , dy4 , dz4 , dw4 )
    # Contribution ( 1,1,0,0)
    dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
    dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
    dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D
    dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D
    attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5
    if attn5 > 0 :
        attn5 *= attn5
        value += attn5 * attn5 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 0 , wsb + 0 , dx5 , dy5 , dz5 , dw5 )
    # Contribution ( 1,0,1,0)
    dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
    dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D
    dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
    dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D
    attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6
    if attn6 > 0 :
        attn6 *= attn6
        value += attn6 * attn6 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 1 , wsb + 0 , dx6 , dy6 , dz6 , dw6 )
    # Contribution ( 1,0,0,1)
    dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
    dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D
    dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D
    dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
    attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7
    if attn7 > 0 :
        attn7 *= attn7
        value += attn7 * attn7 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 0 , wsb + 1 , dx7 , dy7 , dz7 , dw7 )
    # Contribution ( 0,1,1,0)
    dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D
    dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
    dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
    dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D
    attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8
    if attn8 > 0 :
        attn8 *= attn8
        value += attn8 * attn8 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 1 , wsb + 0 , dx8 , dy8 , dz8 , dw8 )
    # Contribution ( 0,1,0,1)
    dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D
    dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
    dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D
    dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
    attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9
    if attn9 > 0 :
        attn9 *= attn9
        value += attn9 * attn9 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 0 , wsb + 1 , dx9 , dy9 , dz9 , dw9 )
    # Contribution ( 0,0,1,1)
    dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D
    dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D
    dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
    dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
    attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10
    if attn10 > 0 :
        attn10 *= attn10
        value += attn10 * attn10 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 1 , wsb + 1 , dx10 , dy10 , dz10 , dw10 )
else : # We ' re inside the second dispentachoron ( Rectified 4 - Simplex )
    a_is_bigger_side = True
    b_is_bigger_side = True
    # Decide between ( 0,0,1,1 ) and ( 1,1,0,0)
    if xins + yins < zins + wins :
        a_score = xins + yins
        a_po = 0x0C
    else :
        a_score = zins + wins
        a_po = 0x03
    # Decide between ( 0,1,0,1 ) and ( 1,0,1,0)
    if xins + zins < yins + wins :
        b_score = xins + zins
        b_po = 0x0A
    else :
        b_score = yins + wins
        b_po = 0x05
    # Closer between ( 0,1,1,0 ) and ( 1,0,0,1 ) will replace the further of a and b , if closer .
    if xins + wins < yins + zins :
        score = xins + wins
        if a_score <= b_score and score < b_score :
            b_score = score
            b_po = 0x06
        elif a_score > b_score and score < a_score :
            a_score = score
            a_po = 0x06
    else :
        score = yins + zins
        if a_score <= b_score and score < b_score :
            b_score = score
            b_po = 0x09
        elif a_score > b_score and score < a_score :
            a_score = score
            a_po = 0x09
    # Decide if ( 0,1,1,1 ) is closer .
    p1 = 3 - in_sum + xins
    if a_score <= b_score and p1 < b_score :
        b_score = p1
        b_po = 0x0E
        b_is_bigger_side = False
    elif a_score > b_score and p1 < a_score :
        a_score = p1
        a_po = 0x0E
        a_is_bigger_side = False
    # Decide if ( 1,0,1,1 ) is closer .
    p2 = 3 - in_sum + yins
    if a_score <= b_score and p2 < b_score :
        b_score = p2
        b_po = 0x0D
        b_is_bigger_side = False
    elif a_score > b_score and p2 < a_score :
        a_score = p2
        a_po = 0x0D
        a_is_bigger_side = False
    # Decide if ( 1,1,0,1 ) is closer .
    p3 = 3 - in_sum + zins
    if a_score <= b_score and p3 < b_score :
        b_score = p3
        b_po = 0x0B
        b_is_bigger_side = False
    elif a_score > b_score and p3 < a_score :
        a_score = p3
        a_po = 0x0B
        a_is_bigger_side = False
    # Decide if ( 1,1,1,0 ) is closer .
    p4 = 3 - in_sum + wins
    if a_score <= b_score and p4 < b_score :
        b_po = 0x07
        b_is_bigger_side = False
    elif a_score > b_score and p4 < a_score :
        a_po = 0x07
        a_is_bigger_side = False
    # Where each of the two closest pos are determines how the extra three vertices are calculated .
    if a_is_bigger_side == b_is_bigger_side :
        if a_is_bigger_side : # Both closest pos on the bigger side
            c1 = ( a_po & b_po )
            c2 = ( a_po | b_po )
            # Two contributions are _ permutations of ( 0,0,0,1 ) and ( 0,0,0,2 ) based on c1
            xsv_ext0 = xsv_ext1 = xsb
            ysv_ext0 = ysv_ext1 = ysb
            zsv_ext0 = zsv_ext1 = zsb
            wsv_ext0 = wsv_ext1 = wsb
            dx_ext0 = dx0 - SQUISH_CONSTANT_4D
            dy_ext0 = dy0 - SQUISH_CONSTANT_4D
            dz_ext0 = dz0 - SQUISH_CONSTANT_4D
            dw_ext0 = dw0 - SQUISH_CONSTANT_4D
            dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_4D
            dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_4D
            dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_4D
            dw_ext1 = dw0 - 2 * SQUISH_CONSTANT_4D
            if ( c1 & 0x01 ) != 0 :
                xsv_ext0 += 1
                dx_ext0 -= 1
                xsv_ext1 += 2
                dx_ext1 -= 2
            elif ( c1 & 0x02 ) != 0 :
                ysv_ext0 += 1
                dy_ext0 -= 1
                ysv_ext1 += 2
                dy_ext1 -= 2
            elif ( c1 & 0x04 ) != 0 :
                zsv_ext0 += 1
                dz_ext0 -= 1
                zsv_ext1 += 2
                dz_ext1 -= 2
            else :
                wsv_ext0 += 1
                dw_ext0 -= 1
                wsv_ext1 += 2
                dw_ext1 -= 2
            # One contribution is a _ permutation of ( 1,1,1 , - 1 ) based on c2
            xsv_ext2 = xsb + 1
            ysv_ext2 = ysb + 1
            zsv_ext2 = zsb + 1
            wsv_ext2 = wsb + 1
            dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
            dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
            dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
            dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
            if ( c2 & 0x01 ) == 0 :
                xsv_ext2 -= 2
                dx_ext2 += 2
            elif ( c2 & 0x02 ) == 0 :
                ysv_ext2 -= 2
                dy_ext2 += 2
            elif ( c2 & 0x04 ) == 0 :
                zsv_ext2 -= 2
                dz_ext2 += 2
            else :
                wsv_ext2 -= 2
                dw_ext2 += 2
        else : # Both closest pos on the smaller side
        # One of the two extra pos is ( 1,1,1,1)
            xsv_ext2 = xsb + 1
            ysv_ext2 = ysb + 1
            zsv_ext2 = zsb + 1
            wsv_ext2 = wsb + 1
            dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D
            dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D
            dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D
            dw_ext2 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D
            # Other two pos are based on the shared axes .
            c = ( a_po & b_po )
            if ( c & 0x01 ) != 0 :
                xsv_ext0 = xsb + 2
                xsv_ext1 = xsb + 1
                dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D
                dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D
            else :
                xsv_ext0 = xsv_ext1 = xsb
                dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D
            if ( c & 0x02 ) != 0 :
                ysv_ext0 = ysv_ext1 = ysb + 1
                dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D
                if ( c & 0x01 ) == 0 :
                    ysv_ext0 += 1
                    dy_ext0 -= 1
                else :
                    ysv_ext1 += 1
                    dy_ext1 -= 1
            else :
                ysv_ext0 = ysv_ext1 = ysb
                dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D
            if ( c & 0x04 ) != 0 :
                zsv_ext0 = zsv_ext1 = zsb + 1
                dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D
                if ( c & 0x03 ) == 0 :
                    zsv_ext0 += 1
                    dz_ext0 -= 1
                else :
                    zsv_ext1 += 1
                    dz_ext1 -= 1
            else :
                zsv_ext0 = zsv_ext1 = zsb
                dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D
            if ( c & 0x08 ) != 0 :
                wsv_ext0 = wsb + 1
                wsv_ext1 = wsb + 2
                dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D
                dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D
            else :
                wsv_ext0 = wsv_ext1 = wsb
                dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D
    else : # One po on each " side "
        if a_is_bigger_side :
            c1 = a_po
            c2 = b_po
        else :
            c1 = b_po
            c2 = a_po
        # Two contributions are the bigger - sided po with each 1 replaced with 2.
        if ( c1 & 0x01 ) != 0 :
            xsv_ext0 = xsb + 2
            xsv_ext1 = xsb + 1
            dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D
            dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D
        else :
            xsv_ext0 = xsv_ext1 = xsb
            dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D
        if ( c1 & 0x02 ) != 0 :
            ysv_ext0 = ysv_ext1 = ysb + 1
            dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D
            if ( c1 & 0x01 ) == 0 :
                ysv_ext0 += 1
                dy_ext0 -= 1
            else :
                ysv_ext1 += 1
                dy_ext1 -= 1
        else :
            ysv_ext0 = ysv_ext1 = ysb
            dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D
        if ( c1 & 0x04 ) != 0 :
            zsv_ext0 = zsv_ext1 = zsb + 1
            dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D
            if ( c1 & 0x03 ) == 0 :
                zsv_ext0 += 1
                dz_ext0 -= 1
            else :
                zsv_ext1 += 1
                dz_ext1 -= 1
        else :
            zsv_ext0 = zsv_ext1 = zsb
            dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D
        if ( c1 & 0x08 ) != 0 :
            wsv_ext0 = wsb + 1
            wsv_ext1 = wsb + 2
            dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D
            dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D
        else :
            wsv_ext0 = wsv_ext1 = wsb
            dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D
        # One contribution is a _ permutation of ( 1,1,1 , - 1 ) based on the smaller - sided po
        xsv_ext2 = xsb + 1
        ysv_ext2 = ysb + 1
        zsv_ext2 = zsb + 1
        wsv_ext2 = wsb + 1
        dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
        dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
        dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
        dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
        if ( c2 & 0x01 ) == 0 :
            xsv_ext2 -= 2
            dx_ext2 += 2
        elif ( c2 & 0x02 ) == 0 :
            ysv_ext2 -= 2
            dy_ext2 += 2
        elif ( c2 & 0x04 ) == 0 :
            zsv_ext2 -= 2
            dz_ext2 += 2
        else :
            wsv_ext2 -= 2
            dw_ext2 += 2
    # Contribution ( 1,1,1,0)
    dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D
    dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D
    dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D
    dw4 = dw0 - 3 * SQUISH_CONSTANT_4D
    attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4
    if attn4 > 0 :
        attn4 *= attn4
        value += attn4 * attn4 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 1 , wsb + 0 , dx4 , dy4 , dz4 , dw4 )
    # Contribution ( 1,1,0,1)
    dx3 = dx4
    dy3 = dy4
    dz3 = dz0 - 3 * SQUISH_CONSTANT_4D
    dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D
    attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3
    if attn3 > 0 :
        attn3 *= attn3
        value += attn3 * attn3 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 0 , wsb + 1 , dx3 , dy3 , dz3 , dw3 )
    # Contribution ( 1,0,1,1)
    dx2 = dx4
    dy2 = dy0 - 3 * SQUISH_CONSTANT_4D
    dz2 = dz4
    dw2 = dw3
    attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2
    if attn2 > 0 :
        attn2 *= attn2
        value += attn2 * attn2 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 1 , wsb + 1 , dx2 , dy2 , dz2 , dw2 )
    # Contribution ( 0,1,1,1)
    dx1 = dx0 - 3 * SQUISH_CONSTANT_4D
    dz1 = dz4
    dy1 = dy4
    dw1 = dw3
    attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1
    if attn1 > 0 :
        attn1 *= attn1
        value += attn1 * attn1 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 1 , wsb + 1 , dx1 , dy1 , dz1 , dw1 )
    # Contribution ( 1,1,0,0)
    dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
    dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
    dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D
    dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D
    attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5
    if attn5 > 0 :
        attn5 *= attn5
        value += attn5 * attn5 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 0 , wsb + 0 , dx5 , dy5 , dz5 , dw5 )
    # Contribution ( 1,0,1,0)
    dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
    dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D
    dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
    dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D
    attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6
    if attn6 > 0 :
        attn6 *= attn6
        value += attn6 * attn6 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 1 , wsb + 0 , dx6 , dy6 , dz6 , dw6 )
    # Contribution ( 1,0,0,1)
    dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D
    dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D
    dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D
    dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
    attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7
    if attn7 > 0 :
        attn7 *= attn7
        value += attn7 * attn7 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 0 , wsb + 1 , dx7 , dy7 , dz7 , dw7 )
    # Contribution ( 0,1,1,0)
    dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D
    dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
    dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
    dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D
    attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8
    if attn8 > 0 :
        attn8 *= attn8
        value += attn8 * attn8 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 1 , wsb + 0 , dx8 , dy8 , dz8 , dw8 )
    # Contribution ( 0,1,0,1)
    dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D
    dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D
    dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D
    dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
    attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9
    if attn9 > 0 :
        attn9 *= attn9
        value += attn9 * attn9 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 0 , wsb + 1 , dx9 , dy9 , dz9 , dw9 )
    # Contribution ( 0,0,1,1)
    dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D
    dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D
    dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D
    dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D
    attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10
    if attn10 > 0 :
        attn10 *= attn10
        value += attn10 * attn10 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 1 , wsb + 1 , dx10 , dy10 , dz10 , dw10 )
# First extra vertex
attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0 - dw_ext0 * dw_ext0
if attn_ext0 > 0 :
    attn_ext0 *= attn_ext0
    value += attn_ext0 * attn_ext0 * extrapolate ( xsv_ext0 , ysv_ext0 , zsv_ext0 , wsv_ext0 , dx_ext0 , dy_ext0 , dz_ext0 , dw_ext0 )
# Second extra vertex
attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1 - dw_ext1 * dw_ext1
if attn_ext1 > 0 :
    attn_ext1 *= attn_ext1
    value += attn_ext1 * attn_ext1 * extrapolate ( xsv_ext1 , ysv_ext1 , zsv_ext1 , wsv_ext1 , dx_ext1 , dy_ext1 , dz_ext1 , dw_ext1 )
# Third extra vertex
attn_ext2 = 2 - dx_ext2 * dx_ext2 - dy_ext2 * dy_ext2 - dz_ext2 * dz_ext2 - dw_ext2 * dw_ext2
if attn_ext2 > 0 :
    attn_ext2 *= attn_ext2
    value += attn_ext2 * attn_ext2 * extrapolate ( xsv_ext2 , ysv_ext2 , zsv_ext2 , wsv_ext2 , dx_ext2 , dy_ext2 , dz_ext2 , dw_ext2 )
return value / NORM_CONSTANT_4D


signature:
def adjust_contrast_gamma ( arr , gamma ) :
    """Adjust contrast by scaling each pixel value to ` ` 255 * ( ( I _ ij / 255 ) * * gamma ) ` ` .
 dtype support : :
 * ` ` uint8 ` ` : yes ; fully tested ( 1 ) ( 2 ) ( 3)
 * ` ` uint16 ` ` : yes ; tested ( 2 ) ( 3)
 * ` ` uint32 ` ` : yes ; tested ( 2 ) ( 3)
 * ` ` uint64 ` ` : yes ; tested ( 2 ) ( 3 ) ( 4)
 * ` ` int8 ` ` : limited ; tested ( 2 ) ( 3 ) ( 5)
 * ` ` int16 ` ` : limited ; tested ( 2 ) ( 3 ) ( 5)
 * ` ` int32 ` ` : limited ; tested ( 2 ) ( 3 ) ( 5)
 * ` ` int64 ` ` : limited ; tested ( 2 ) ( 3 ) ( 4 ) ( 5)
 * ` ` float16 ` ` : limited ; tested ( 5)
 * ` ` float32 ` ` : limited ; tested ( 5)
 * ` ` float64 ` ` : limited ; tested ( 5)
 * ` ` float128 ` ` : no ( 6)
 * ` ` bool ` ` : no ( 7)
 - ( 1 ) Handled by ` ` cv2 ` ` . Other dtypes are handled by ` ` skimage ` ` .
 - ( 2 ) Normalization is done as ` ` I _ ij / max ` ` , where ` ` max ` ` is the maximum value of the
 dtype , e . g . 255 for ` ` uint8 ` ` . The normalization is reversed afterwards ,
 e . g . ` ` result * 255 ` ` for ` ` uint8 ` ` .
 - ( 3 ) Integer - like values are not rounded after applying the contrast adjustment equation
 ( before inverting the normalization to 0.0-1.0 space ) , i . e . projection from continuous
 space to discrete happens according to floor function .
 - ( 4 ) Note that scikit - image doc says that integers are converted to ` ` float64 ` ` values before
 applying the contrast normalization method . This might lead to inaccuracies for large
 64bit integer values . Tests showed no indication of that happening though .
 - ( 5 ) Must not contain negative values . Values > = 0 are fully supported .
 - ( 6 ) Leads to error in scikit - image .
 - ( 7 ) Does not make sense for contrast adjustments .
 Parameters
 arr : numpy . ndarray
 Array for which to adjust the contrast . Dtype ` ` uint8 ` ` is fastest .
 gamma : number
 Exponent for the contrast adjustment . Higher values darken the image .
 Returns
 numpy . ndarray
 Array with adjusted contrast ."""

implementation:
# int8 is also possible according to docs
# https : / / docs . opencv . org / 3.0 - beta / modules / core / doc / operations _ on _ arrays . html # cv2 . LUT , but here it seemed
# like ` d ` was 0 for CV _ 8S , causing that to fail
if arr . dtype . name == "uint8" :
    min_value , _center_value , max_value = iadt . get_value_range_of_dtype ( arr . dtype )
    dynamic_range = max_value - min_value
    value_range = np . linspace ( 0 , 1.0 , num = dynamic_range + 1 , dtype = np . float32 )
    # 255 * ( ( I _ ij / 255 ) * * gamma )
    # using np . float32 ( . ) here still works when the input is a numpy array of size 1
    table = ( min_value + ( value_range ** np . float32 ( gamma ) ) * dynamic_range )
    arr_aug = cv2 . LUT ( arr , np . clip ( table , min_value , max_value ) . astype ( arr . dtype ) )
    if arr . ndim == 3 and arr_aug . ndim == 2 :
        return arr_aug [ ... , np . newaxis ]
    return arr_aug
else :
    return ski_exposure . adjust_gamma ( arr , gamma )


signature:
def adjust_contrast_sigmoid ( arr , gain , cutoff ) :
    """Adjust contrast by scaling each pixel value to ` ` 255 * 1 / ( 1 + exp ( gain * ( cutoff - I _ ij / 255 ) ) ) ` ` .
 dtype support : :
 * ` ` uint8 ` ` : yes ; fully tested ( 1 ) ( 2 ) ( 3)
 * ` ` uint16 ` ` : yes ; tested ( 2 ) ( 3)
 * ` ` uint32 ` ` : yes ; tested ( 2 ) ( 3)
 * ` ` uint64 ` ` : yes ; tested ( 2 ) ( 3 ) ( 4)
 * ` ` int8 ` ` : limited ; tested ( 2 ) ( 3 ) ( 5)
 * ` ` int16 ` ` : limited ; tested ( 2 ) ( 3 ) ( 5)
 * ` ` int32 ` ` : limited ; tested ( 2 ) ( 3 ) ( 5)
 * ` ` int64 ` ` : limited ; tested ( 2 ) ( 3 ) ( 4 ) ( 5)
 * ` ` float16 ` ` : limited ; tested ( 5)
 * ` ` float32 ` ` : limited ; tested ( 5)
 * ` ` float64 ` ` : limited ; tested ( 5)
 * ` ` float128 ` ` : no ( 6)
 * ` ` bool ` ` : no ( 7)
 - ( 1 ) Handled by ` ` cv2 ` ` . Other dtypes are handled by ` ` skimage ` ` .
 - ( 2 ) Normalization is done as ` ` I _ ij / max ` ` , where ` ` max ` ` is the maximum value of the
 dtype , e . g . 255 for ` ` uint8 ` ` . The normalization is reversed afterwards ,
 e . g . ` ` result * 255 ` ` for ` ` uint8 ` ` .
 - ( 3 ) Integer - like values are not rounded after applying the contrast adjustment equation
 ( before inverting the normalization to 0.0-1.0 space ) , i . e . projection from continuous
 space to discrete happens according to floor function .
 - ( 4 ) Note that scikit - image doc says that integers are converted to ` ` float64 ` ` values before
 applying the contrast normalization method . This might lead to inaccuracies for large
 64bit integer values . Tests showed no indication of that happening though .
 - ( 5 ) Must not contain negative values . Values > = 0 are fully supported .
 - ( 6 ) Leads to error in scikit - image .
 - ( 7 ) Does not make sense for contrast adjustments .
 Parameters
 arr : numpy . ndarray
 Array for which to adjust the contrast . Dtype ` ` uint8 ` ` is fastest .
 gain : number
 Multiplier for the sigmoid function ' s output .
 Higher values lead to quicker changes from dark to light pixels .
 cutoff : number
 Cutoff that shifts the sigmoid function in horizontal direction .
 Higher values mean that the switch from dark to light pixels happens later , i . e .
 the pixels will remain darker .
 Returns
 numpy . ndarray
 Array with adjusted contrast ."""

implementation:
# int8 is also possible according to docs
# https : / / docs . opencv . org / 3.0 - beta / modules / core / doc / operations _ on _ arrays . html # cv2 . LUT , but here it seemed
# like ` d ` was 0 for CV _ 8S , causing that to fail
if arr . dtype . name == "uint8" :
    min_value , _center_value , max_value = iadt . get_value_range_of_dtype ( arr . dtype )
    dynamic_range = max_value - min_value
    value_range = np . linspace ( 0 , 1.0 , num = dynamic_range + 1 , dtype = np . float32 )
    # 255 * 1 / ( 1 + exp ( gain * ( cutoff - I _ ij / 255 ) ) )
    # using np . float32 ( . ) here still works when the input is a numpy array of size 1
    gain = np . float32 ( gain )
    cutoff = np . float32 ( cutoff )
    table = min_value + dynamic_range * 1 / ( 1 + np . exp ( gain * ( cutoff - value_range ) ) )
    arr_aug = cv2 . LUT ( arr , np . clip ( table , min_value , max_value ) . astype ( arr . dtype ) )
    if arr . ndim == 3 and arr_aug . ndim == 2 :
        return arr_aug [ ... , np . newaxis ]
    return arr_aug
else :
    return ski_exposure . adjust_sigmoid ( arr , cutoff = cutoff , gain = gain )


signature:
def adjust_contrast_log ( arr , gain ) :
    """Adjust contrast by scaling each pixel value to ` ` 255 * gain * log _ 2(1 + I _ ij / 255 ) ` ` .
 dtype support : :
 * ` ` uint8 ` ` : yes ; fully tested ( 1 ) ( 2 ) ( 3)
 * ` ` uint16 ` ` : yes ; tested ( 2 ) ( 3)
 * ` ` uint32 ` ` : yes ; tested ( 2 ) ( 3)
 * ` ` uint64 ` ` : yes ; tested ( 2 ) ( 3 ) ( 4)
 * ` ` int8 ` ` : limited ; tested ( 2 ) ( 3 ) ( 5)
 * ` ` int16 ` ` : limited ; tested ( 2 ) ( 3 ) ( 5)
 * ` ` int32 ` ` : limited ; tested ( 2 ) ( 3 ) ( 5)
 * ` ` int64 ` ` : limited ; tested ( 2 ) ( 3 ) ( 4 ) ( 5)
 * ` ` float16 ` ` : limited ; tested ( 5)
 * ` ` float32 ` ` : limited ; tested ( 5)
 * ` ` float64 ` ` : limited ; tested ( 5)
 * ` ` float128 ` ` : no ( 6)
 * ` ` bool ` ` : no ( 7)
 - ( 1 ) Handled by ` ` cv2 ` ` . Other dtypes are handled by ` ` skimage ` ` .
 - ( 2 ) Normalization is done as ` ` I _ ij / max ` ` , where ` ` max ` ` is the maximum value of the
 dtype , e . g . 255 for ` ` uint8 ` ` . The normalization is reversed afterwards ,
 e . g . ` ` result * 255 ` ` for ` ` uint8 ` ` .
 - ( 3 ) Integer - like values are not rounded after applying the contrast adjustment equation
 ( before inverting the normalization to 0.0-1.0 space ) , i . e . projection from continuous
 space to discrete happens according to floor function .
 - ( 4 ) Note that scikit - image doc says that integers are converted to ` ` float64 ` ` values before
 applying the contrast normalization method . This might lead to inaccuracies for large
 64bit integer values . Tests showed no indication of that happening though .
 - ( 5 ) Must not contain negative values . Values > = 0 are fully supported .
 - ( 6 ) Leads to error in scikit - image .
 - ( 7 ) Does not make sense for contrast adjustments .
 Parameters
 arr : numpy . ndarray
 Array for which to adjust the contrast . Dtype ` ` uint8 ` ` is fastest .
 gain : number
 Multiplier for the logarithm result . Values around 1.0 lead to a contrast - adjusted
 images . Values above 1.0 quickly lead to partially broken images due to exceeding the
 datatype ' s value range .
 Returns
 numpy . ndarray
 Array with adjusted contrast ."""

implementation:
# int8 is also possible according to docs
# https : / / docs . opencv . org / 3.0 - beta / modules / core / doc / operations _ on _ arrays . html # cv2 . LUT , but here it seemed
# like ` d ` was 0 for CV _ 8S , causing that to fail
if arr . dtype . name == "uint8" :
    min_value , _center_value , max_value = iadt . get_value_range_of_dtype ( arr . dtype )
    dynamic_range = max_value - min_value
    value_range = np . linspace ( 0 , 1.0 , num = dynamic_range + 1 , dtype = np . float32 )
    # 255 * 1 / ( 1 + exp ( gain * ( cutoff - I _ ij / 255 ) ) )
    # using np . float32 ( . ) here still works when the input is a numpy array of size 1
    gain = np . float32 ( gain )
    table = min_value + dynamic_range * gain * np . log2 ( 1 + value_range )
    arr_aug = cv2 . LUT ( arr , np . clip ( table , min_value , max_value ) . astype ( arr . dtype ) )
    if arr . ndim == 3 and arr_aug . ndim == 2 :
        return arr_aug [ ... , np . newaxis ]
    return arr_aug
else :
    return ski_exposure . adjust_log ( arr , gain = gain )


signature:
def adjust_contrast_linear ( arr , alpha ) :
    """Adjust contrast by scaling each pixel value to ` ` 127 + alpha * ( I _ ij - 127 ) ` ` .
 dtype support : :
 * ` ` uint8 ` ` : yes ; fully tested ( 1 ) ( 2)
 * ` ` uint16 ` ` : yes ; tested ( 2)
 * ` ` uint32 ` ` : yes ; tested ( 2)
 * ` ` uint64 ` ` : no ( 3)
 * ` ` int8 ` ` : yes ; tested ( 2)
 * ` ` int16 ` ` : yes ; tested ( 2)
 * ` ` int32 ` ` : yes ; tested ( 2)
 * ` ` int64 ` ` : no ( 2)
 * ` ` float16 ` ` : yes ; tested ( 2)
 * ` ` float32 ` ` : yes ; tested ( 2)
 * ` ` float64 ` ` : yes ; tested ( 2)
 * ` ` float128 ` ` : no ( 2)
 * ` ` bool ` ` : no ( 4)
 - ( 1 ) Handled by ` ` cv2 ` ` . Other dtypes are handled by raw ` ` numpy ` ` .
 - ( 2 ) Only tested for reasonable alphas with up to a value of around 100.
 - ( 3 ) Conversion to ` ` float64 ` ` is done during augmentation , hence ` ` uint64 ` ` , ` ` int64 ` ` ,
 and ` ` float128 ` ` support cannot be guaranteed .
 - ( 4 ) Does not make sense for contrast adjustments .
 Parameters
 arr : numpy . ndarray
 Array for which to adjust the contrast . Dtype ` ` uint8 ` ` is fastest .
 alpha : number
 Multiplier to linearly pronounce ( > 1.0 ) , dampen ( 0.0 to 1.0 ) or invert ( < 0.0 ) the
 difference between each pixel value and the center value , e . g . ` ` 127 ` ` for ` ` uint8 ` ` .
 Returns
 numpy . ndarray
 Array with adjusted contrast ."""

implementation:
# int8 is also possible according to docs
# https : / / docs . opencv . org / 3.0 - beta / modules / core / doc / operations _ on _ arrays . html # cv2 . LUT , but here it seemed
# like ` d ` was 0 for CV _ 8S , causing that to fail
if arr . dtype . name == "uint8" :
    min_value , center_value , max_value = iadt . get_value_range_of_dtype ( arr . dtype )
    value_range = np . arange ( 0 , 256 , dtype = np . float32 )
    # 127 + alpha * ( I _ ij - 127)
    # using np . float32 ( . ) here still works when the input is a numpy array of size 1
    alpha = np . float32 ( alpha )
    table = center_value + alpha * ( value_range - center_value )
    arr_aug = cv2 . LUT ( arr , np . clip ( table , min_value , max_value ) . astype ( arr . dtype ) )
    if arr . ndim == 3 and arr_aug . ndim == 2 :
        return arr_aug [ ... , np . newaxis ]
    return arr_aug
else :
    input_dtype = arr . dtype
    _min_value , center_value , _max_value = iadt . get_value_range_of_dtype ( input_dtype )
    if input_dtype . kind in [ "u" , "i" ] :
        center_value = int ( center_value )
    image_aug = center_value + alpha * ( arr . astype ( np . float64 ) - center_value )
    image_aug = iadt . restore_dtypes_ ( image_aug , input_dtype )
    return image_aug


signature:
def GammaContrast ( gamma = 1 , per_channel = False , name = None , deterministic = False , random_state = None ) :
    """Adjust contrast by scaling each pixel value to ` ` 255 * ( ( I _ ij / 255 ) * * gamma ) ` ` .
 Values in the range ` ` gamma = ( 0.5 , 2.0 ) ` ` seem to be sensible .
 dtype support : :
 See : func : ` imgaug . augmenters . contrast . adjust _ contrast _ gamma ` .
 Parameters
 gamma : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Exponent for the contrast adjustment . Higher values darken the image .
 * If a number , then that value will be used for all images .
 * If a tuple ` ` ( a , b ) ` ` , then a value from the range ` ` [ a , b ] ` ` will be used per image .
 * If a list , then a random value will be sampled from that list per image .
 * If a StochasticParameter , then a value will be sampled per image from that parameter .
 per _ channel : bool or float , optional
 Whether to use the same value for all channels ( False ) or to sample a new value for each
 channel ( True ) . If this value is a float ` ` p ` ` , then for ` ` p ` ` percent of all images ` per _ channel `
 will be treated as True , otherwise as False .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Returns
 _ ContrastFuncWrapper
 Augmenter to perform gamma contrast adjustment ."""

implementation:
params1d = [ iap . handle_continuous_param ( gamma , "gamma" , value_range = None , tuple_to_uniform = True , list_to_choice = True ) ]
func = adjust_contrast_gamma
return _ContrastFuncWrapper ( func , params1d , per_channel , dtypes_allowed = [ "uint8" , "uint16" , "uint32" , "uint64" , "int8" , "int16" , "int32" , "int64" , "float16" , "float32" , "float64" ] , dtypes_disallowed = [ "float96" , "float128" , "float256" , "bool" ] , name = name if name is not None else ia . caller_name ( ) , deterministic = deterministic , random_state = random_state )


signature:
def SigmoidContrast ( gain = 10 , cutoff = 0.5 , per_channel = False , name = None , deterministic = False , random_state = None ) :
    """Adjust contrast by scaling each pixel value to ` ` 255 * 1 / ( 1 + exp ( gain * ( cutoff - I _ ij / 255 ) ) ) ` ` .
 Values in the range ` ` gain = ( 5 , 20 ) ` ` and ` ` cutoff = ( 0.25 , 0.75 ) ` ` seem to be sensible .
 dtype support : :
 See : func : ` imgaug . augmenters . contrast . adjust _ contrast _ sigmoid ` .
 Parameters
 gain : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Multiplier for the sigmoid function ' s output .
 Higher values lead to quicker changes from dark to light pixels .
 * If a number , then that value will be used for all images .
 * If a tuple ` ` ( a , b ) ` ` , then a value from the range ` ` [ a , b ] ` ` will be used per image .
 * If a list , then a random value will be sampled from that list per image .
 * If a StochasticParameter , then a value will be sampled per image from that parameter .
 cutoff : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Cutoff that shifts the sigmoid function in horizontal direction .
 Higher values mean that the switch from dark to light pixels happens later , i . e .
 the pixels will remain darker .
 * If a number , then that value will be used for all images .
 * If a tuple ` ` ( a , b ) ` ` , then a value from the range ` ` [ a , b ] ` ` will be used per image .
 * If a list , then a random value will be sampled from that list per image .
 * If a StochasticParameter , then a value will be sampled per image from that parameter .
 per _ channel : bool or float , optional
 Whether to use the same value for all channels ( False ) or to sample a new value for each
 channel ( True ) . If this value is a float ` ` p ` ` , then for ` ` p ` ` percent of all images ` per _ channel `
 will be treated as True , otherwise as False .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Returns
 _ ContrastFuncWrapper
 Augmenter to perform sigmoid contrast adjustment ."""

implementation:
# TODO add inv parameter ?
params1d = [ iap . handle_continuous_param ( gain , "gain" , value_range = ( 0 , None ) , tuple_to_uniform = True , list_to_choice = True ) , iap . handle_continuous_param ( cutoff , "cutoff" , value_range = ( 0 , 1.0 ) , tuple_to_uniform = True , list_to_choice = True ) ]
func = adjust_contrast_sigmoid
return _ContrastFuncWrapper ( func , params1d , per_channel , dtypes_allowed = [ "uint8" , "uint16" , "uint32" , "uint64" , "int8" , "int16" , "int32" , "int64" , "float16" , "float32" , "float64" ] , dtypes_disallowed = [ "float96" , "float128" , "float256" , "bool" ] , name = name if name is not None else ia . caller_name ( ) , deterministic = deterministic , random_state = random_state )


signature:
def LogContrast ( gain = 1 , per_channel = False , name = None , deterministic = False , random_state = None ) :
    """Adjust contrast by scaling each pixel value to ` ` 255 * gain * log _ 2(1 + I _ ij / 255 ) ` ` .
 dtype support : :
 See : func : ` imgaug . augmenters . contrast . adjust _ contrast _ log ` .
 Parameters
 gain : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Multiplier for the logarithm result . Values around 1.0 lead to a contrast - adjusted
 images . Values above 1.0 quickly lead to partially broken images due to exceeding the
 datatype ' s value range .
 * If a number , then that value will be used for all images .
 * If a tuple ` ` ( a , b ) ` ` , then a value from the range ` ` [ a , b ] ` ` will be used per image .
 * If a list , then a random value will be sampled from that list per image .
 * If a StochasticParameter , then a value will be sampled per image from that parameter .
 per _ channel : bool or float , optional
 Whether to use the same value for all channels ( False ) or to sample a new value for each
 channel ( True ) . If this value is a float ` ` p ` ` , then for ` ` p ` ` percent of all images ` per _ channel `
 will be treated as True , otherwise as False .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Returns
 _ ContrastFuncWrapper
 Augmenter to perform logarithmic contrast adjustment ."""

implementation:
# TODO add inv parameter ?
params1d = [ iap . handle_continuous_param ( gain , "gain" , value_range = ( 0 , None ) , tuple_to_uniform = True , list_to_choice = True ) ]
func = adjust_contrast_log
return _ContrastFuncWrapper ( func , params1d , per_channel , dtypes_allowed = [ "uint8" , "uint16" , "uint32" , "uint64" , "int8" , "int16" , "int32" , "int64" , "float16" , "float32" , "float64" ] , dtypes_disallowed = [ "float96" , "float128" , "float256" , "bool" ] , name = name if name is not None else ia . caller_name ( ) , deterministic = deterministic , random_state = random_state )


signature:
def LinearContrast ( alpha = 1 , per_channel = False , name = None , deterministic = False , random_state = None ) :
    """Adjust contrast by scaling each pixel value to ` ` 127 + alpha * ( I _ ij - 127 ) ` ` .
 dtype support : :
 See : func : ` imgaug . augmenters . contrast . adjust _ contrast _ linear ` .
 Parameters
 alpha : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 Multiplier to linearly pronounce ( > 1.0 ) , dampen ( 0.0 to 1.0 ) or invert ( < 0.0 ) the
 difference between each pixel value and the center value , e . g . ` ` 127 ` ` for ` ` uint8 ` ` .
 * If a number , then that value will be used for all images .
 * If a tuple ` ` ( a , b ) ` ` , then a value from the range ` ` [ a , b ] ` ` will be used per image .
 * If a list , then a random value will be sampled from that list per image .
 * If a StochasticParameter , then a value will be sampled per image from that parameter .
 per _ channel : bool or float , optional
 Whether to use the same value for all channels ( False ) or to sample a new value for each
 channel ( True ) . If this value is a float ` ` p ` ` , then for ` ` p ` ` percent of all images ` per _ channel `
 will be treated as True , otherwise as False .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Returns
 _ ContrastFuncWrapper
 Augmenter to perform contrast adjustment by linearly scaling the distance to 128."""

implementation:
params1d = [ iap . handle_continuous_param ( alpha , "alpha" , value_range = None , tuple_to_uniform = True , list_to_choice = True ) ]
func = adjust_contrast_linear
return _ContrastFuncWrapper ( func , params1d , per_channel , dtypes_allowed = [ "uint8" , "uint16" , "uint32" , "int8" , "int16" , "int32" , "float16" , "float32" , "float64" ] , dtypes_disallowed = [ "uint64" , "int64" , "float96" , "float128" , "float256" , "bool" ] , name = name if name is not None else ia . caller_name ( ) , deterministic = deterministic , random_state = random_state )


signature:
def InColorspace ( to_colorspace , from_colorspace = "RGB" , children = None , name = None , deterministic = False , random_state = None ) :
    """Convert images to another colorspace ."""

implementation: return WithColorspace ( to_colorspace , from_colorspace , children , name , deterministic , random_state )


signature:
def Grayscale ( alpha = 0 , from_colorspace = "RGB" , name = None , deterministic = False , random_state = None ) :
    """Augmenter to convert images to their grayscale versions .
 NOTE : Number of output channels is still 3 , i . e . this augmenter just " removes " color .
 TODO check dtype support
 dtype support : :
 * ` ` uint8 ` ` : yes ; fully tested
 * ` ` uint16 ` ` : ?
 * ` ` uint32 ` ` : ?
 * ` ` uint64 ` ` : ?
 * ` ` int8 ` ` : ?
 * ` ` int16 ` ` : ?
 * ` ` int32 ` ` : ?
 * ` ` int64 ` ` : ?
 * ` ` float16 ` ` : ?
 * ` ` float32 ` ` : ?
 * ` ` float64 ` ` : ?
 * ` ` float128 ` ` : ?
 * ` ` bool ` ` : ?
 Parameters
 alpha : number or tuple of number or list of number or imgaug . parameters . StochasticParameter , optional
 The alpha value of the grayscale image when overlayed over the
 old image . A value close to 1.0 means , that mostly the new grayscale
 image is visible . A value close to 0.0 means , that mostly the
 old image is visible .
 * If a number , exactly that value will always be used .
 * If a tuple ` ` ( a , b ) ` ` , a random value from the range ` ` a < = x < = b ` ` will
 be sampled per image .
 * If a list , then a random value will be sampled from that list per image .
 * If a StochasticParameter , a value will be sampled from the
 parameter per image .
 from _ colorspace : str , optional
 The source colorspace ( of the input images ) .
 Allowed strings are : ` ` RGB ` ` , ` ` BGR ` ` , ` ` GRAY ` ` , ` ` CIE ` ` , ` ` YCrCb ` ` , ` ` HSV ` ` , ` ` HLS ` ` , ` ` Lab ` ` , ` ` Luv ` ` .
 See : func : ` imgaug . augmenters . color . ChangeColorspace . _ _ init _ _ ` .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Examples
 > > > aug = iaa . Grayscale ( alpha = 1.0)
 creates an augmenter that turns images to their grayscale versions .
 > > > aug = iaa . Grayscale ( alpha = ( 0.0 , 1.0 ) )
 creates an augmenter that turns images to their grayscale versions with
 an alpha value in the range ` ` 0 < = alpha < = 1 ` ` . An alpha value of 0.5 would
 mean , that the output image is 50 percent of the input image and 50
 percent of the grayscale image ( i . e . 50 percent of color removed ) ."""

implementation:
if name is None :
    name = "Unnamed%s" % ( ia . caller_name ( ) , )
return ChangeColorspace ( to_colorspace = ChangeColorspace . GRAY , alpha = alpha , from_colorspace = from_colorspace , name = name , deterministic = deterministic , random_state = random_state )


signature:
def height ( self ) :
    """Get the height of a bounding box encapsulating the line ."""

implementation:
if len ( self . coords ) <= 1 :
    return 0
return np . max ( self . yy ) - np . min ( self . yy )


signature:
def width ( self ) :
    """Get the width of a bounding box encapsulating the line ."""

implementation:
if len ( self . coords ) <= 1 :
    return 0
return np . max ( self . xx ) - np . min ( self . xx )


signature:
def get_pointwise_inside_image_mask ( self , image ) :
    """Get for each point whether it is inside of the given image plane .
 Parameters
 image : ndarray or tuple of int
 Either an image with shape ` ` ( H , W , [ C ] ) ` ` or a tuple denoting
 such an image shape .
 Returns
 ndarray
 Boolean array with one value per point indicating whether it is
 inside of the provided image plane ( ` ` True ` ` ) or not ( ` ` False ` ` ) ."""

implementation:
if len ( self . coords ) == 0 :
    return np . zeros ( ( 0 , ) , dtype = bool )
shape = normalize_shape ( image )
height , width = shape [ 0 : 2 ]
x_within = np . logical_and ( 0 <= self . xx , self . xx < width )
y_within = np . logical_and ( 0 <= self . yy , self . yy < height )
return np . logical_and ( x_within , y_within )


signature:
def compute_neighbour_distances ( self ) :
    """Get the euclidean distance between each two consecutive points .
 Returns
 ndarray
 Euclidean distances between point pairs .
 Same order as in ` coords ` . For ` ` N ` ` points , ` ` N - 1 ` ` distances
 are returned ."""

implementation:
if len ( self . coords ) <= 1 :
    return np . zeros ( ( 0 , ) , dtype = np . float32 )
return np . sqrt ( np . sum ( ( self . coords [ : - 1 , : ] - self . coords [ 1 : , : ] ) ** 2 , axis = 1 ) )


signature:
def compute_pointwise_distances ( self , other , default = None ) :
    """Compute the minimal distance between each point on self and other .
 Parameters
 other : tuple of number or imgaug . augmentables . kps . Keypoint or imgaug . augmentables . LineString
 Other object to which to compute the distances .
 default
 Value to return if ` other ` contains no points .
 Returns
 list of float
 Distances to ` other ` or ` default ` if not distance could be computed ."""

implementation:
import shapely . geometry
from . kps import Keypoint
if isinstance ( other , Keypoint ) :
    other = shapely . geometry . Point ( ( other . x , other . y ) )
elif isinstance ( other , LineString ) :
    if len ( other . coords ) == 0 :
        return default
    elif len ( other . coords ) == 1 :
        other = shapely . geometry . Point ( other . coords [ 0 , : ] )
    else :
        other = shapely . geometry . LineString ( other . coords )
elif isinstance ( other , tuple ) :
    assert len ( other ) == 2
    other = shapely . geometry . Point ( other )
else :
    raise ValueError ( ( "Expected Keypoint or LineString or tuple (x,y), " + "got type %s." ) % ( type ( other ) , ) )
return [ shapely . geometry . Point ( point ) . distance ( other ) for point in self . coords ]


signature:
def compute_distance ( self , other , default = None ) :
    """Compute the minimal distance between the line string and ` other ` .
 Parameters
 other : tuple of number or imgaug . augmentables . kps . Keypoint or imgaug . augmentables . LineString
 Other object to which to compute the distance .
 default
 Value to return if this line string or ` other ` contain no points .
 Returns
 float
 Distance to ` other ` or ` default ` if not distance could be computed ."""

implementation:
# FIXME this computes distance pointwise , does not have to be identical
# with the actual min distance ( e . g . edge center to other ' s point )
distances = self . compute_pointwise_distances ( other , default = [ ] )
if len ( distances ) == 0 :
    return default
return min ( distances )


signature:
def contains ( self , other , max_distance = 1e-4 ) :
    """Estimate whether the bounding box contains a point .
 Parameters
 other : tuple of number or imgaug . augmentables . kps . Keypoint
 Point to check for .
 max _ distance : float
 Maximum allowed euclidean distance between the point and the
 closest point on the line . If the threshold is exceeded , the point
 is not considered to be contained in the line .
 Returns
 bool
 True if the point is contained in the line string , False otherwise .
 It is contained if its distance to the line or any of its points
 is below a threshold ."""

implementation: return self . compute_distance ( other , default = np . inf ) < max_distance


signature:
def project ( self , from_shape , to_shape ) :
    """Project the line string onto a differently shaped image .
 E . g . if a point of the line string is on its original image at
 ` ` x = ( 10 of 100 pixels ) ` ` and ` ` y = ( 20 of 100 pixels ) ` ` and is projected
 onto a new image with size ` ` ( width = 200 , height = 200 ) ` ` , its new
 position will be ` ` ( x = 20 , y = 40 ) ` ` .
 This is intended for cases where the original image is resized .
 It cannot be used for more complex changes ( e . g . padding , cropping ) .
 Parameters
 from _ shape : tuple of int or ndarray
 Shape of the original image . ( Before resize . )
 to _ shape : tuple of int or ndarray
 Shape of the new image . ( After resize . )
 Returns
 out : imgaug . augmentables . lines . LineString
 Line string with new coordinates ."""

implementation:
coords_proj = project_coords ( self . coords , from_shape , to_shape )
return self . copy ( coords = coords_proj )


signature:
def is_fully_within_image ( self , image , default = False ) :
    """Estimate whether the line string is fully inside the image area .
 Parameters
 image : ndarray or tuple of int
 Either an image with shape ` ` ( H , W , [ C ] ) ` ` or a tuple denoting
 such an image shape .
 default
 Default value to return if the line string contains no points .
 Returns
 bool
 True if the line string is fully inside the image area .
 False otherwise ."""

implementation:
if len ( self . coords ) == 0 :
    return default
return np . all ( self . get_pointwise_inside_image_mask ( image ) )


signature:
def is_partly_within_image ( self , image , default = False ) :
    """Estimate whether the line string is at least partially inside the image .
 Parameters
 image : ndarray or tuple of int
 Either an image with shape ` ` ( H , W , [ C ] ) ` ` or a tuple denoting
 such an image shape .
 default
 Default value to return if the line string contains no points .
 Returns
 bool
 True if the line string is at least partially inside the image area .
 False otherwise ."""

implementation:
if len ( self . coords ) == 0 :
    return default
# check mask first to avoid costly computation of intersection points
# whenever possible
mask = self . get_pointwise_inside_image_mask ( image )
if np . any ( mask ) :
    return True
return len ( self . clip_out_of_image ( image ) ) > 0


signature:
def is_out_of_image ( self , image , fully = True , partly = False , default = True ) :
    """Estimate whether the line is partially / fully outside of the image area .
 Parameters
 image : ndarray or tuple of int
 Either an image with shape ` ` ( H , W , [ C ] ) ` ` or a tuple denoting
 such an image shape .
 fully : bool , optional
 Whether to return True if the bounding box is fully outside fo the
 image area .
 partly : bool , optional
 Whether to return True if the bounding box is at least partially
 outside fo the image area .
 default
 Default value to return if the line string contains no points .
 Returns
 bool
 ` default ` if the line string has no points .
 True if the line string is partially / fully outside of the image
 area , depending on defined parameters .
 False otherwise ."""

implementation:
if len ( self . coords ) == 0 :
    return default
if self . is_fully_within_image ( image ) :
    return False
elif self . is_partly_within_image ( image ) :
    return partly
else :
    return fully


signature:
def clip_out_of_image ( self , image ) :
    """Clip off all parts of the line _ string that are outside of the image .
 Parameters
 image : ndarray or tuple of int
 Either an image with shape ` ` ( H , W , [ C ] ) ` ` or a tuple denoting
 such an image shape .
 Returns
 list of imgaug . augmentables . lines . LineString
 Line strings , clipped to the image shape .
 The result may contain any number of line strins , including zero ."""

implementation:
if len ( self . coords ) == 0 :
    return [ ]
inside_image_mask = self . get_pointwise_inside_image_mask ( image )
ooi_mask = ~ inside_image_mask
if len ( self . coords ) == 1 :
    if not np . any ( inside_image_mask ) :
        return [ ]
    return [ self . copy ( ) ]
if np . all ( inside_image_mask ) :
    return [ self . copy ( ) ]
# top , right , bottom , left image edges
# we subtract eps here , because intersection ( ) works inclusively ,
# i . e . not subtracting eps would be equivalent to 0 < = x < = C for C being
# height or width
# don ' t set the eps too low , otherwise points at height / width seem
# to get rounded to height / width by shapely , which can cause problems
# when first clipping and then calling is _ fully _ within _ image ( )
# returning false
height , width = normalize_shape ( image ) [ 0 : 2 ]
eps = 1e-3
edges = [ LineString ( [ ( 0.0 , 0.0 ) , ( width - eps , 0.0 ) ] ) , LineString ( [ ( width - eps , 0.0 ) , ( width - eps , height - eps ) ] ) , LineString ( [ ( width - eps , height - eps ) , ( 0.0 , height - eps ) ] ) , LineString ( [ ( 0.0 , height - eps ) , ( 0.0 , 0.0 ) ] ) ]
intersections = self . find_intersections_with ( edges )
points = [ ]
gen = enumerate ( zip ( self . coords [ : - 1 ] , self . coords [ 1 : ] , ooi_mask [ : - 1 ] , ooi_mask [ 1 : ] , intersections ) )
for i , ( line_start , line_end , ooi_start , ooi_end , inter_line ) in gen :
    points . append ( ( line_start , False , ooi_start ) )
    for p_inter in inter_line :
        points . append ( ( p_inter , True , False ) )
    is_last = ( i == len ( self . coords ) - 2 )
    if is_last and not ooi_end :
        points . append ( ( line_end , False , ooi_end ) )
lines = [ ]
line = [ ]
for i , ( coord , was_added , ooi ) in enumerate ( points ) : # remove any point that is outside of the image ,
# also start a new line once such a point is detected
    if ooi :
        if len ( line ) > 0 :
            lines . append ( line )
            line = [ ]
        continue
    if not was_added : # add all points that were part of the original line string
    # AND that are inside the image plane
        line . append ( coord )
    else :
        is_last_point = ( i == len ( points ) - 1 )
        # ooi is a numpy . bool _ , hence the bool ( . )
        is_next_ooi = ( not is_last_point and bool ( points [ i + 1 ] [ 2 ] ) is True )
        # Add all points that were new ( i . e . intersections ) , so
        # long that they aren ' t essentially identical to other point .
        # This prevents adding overlapping intersections multiple times .
        # ( E . g . when a line intersects with a corner of the image plane
        # and also with one of its edges . )
        p_prev = line [ - 1 ] if len ( line ) > 0 else None
        # ignore next point if end reached or next point is out of image
        p_next = None
        if not is_last_point and not is_next_ooi :
            p_next = points [ i + 1 ] [ 0 ]
        dist_prev = None
        dist_next = None
        if p_prev is not None :
            dist_prev = np . linalg . norm ( np . float32 ( coord ) - np . float32 ( p_prev ) )
        if p_next is not None :
            dist_next = np . linalg . norm ( np . float32 ( coord ) - np . float32 ( p_next ) )
        dist_prev_ok = ( dist_prev is None or dist_prev > 1e-2 )
        dist_next_ok = ( dist_next is None or dist_next > 1e-2 )
        if dist_prev_ok and dist_next_ok :
            line . append ( coord )
if len ( line ) > 0 :
    lines . append ( line )
lines = [ line for line in lines if len ( line ) > 0 ]
return [ self . deepcopy ( coords = line ) for line in lines ]


signature:
def find_intersections_with ( self , other ) :
    """Find all intersection points between the line string and ` other ` .
 Parameters
 other : tuple of number or list of tuple of number or list of LineString or LineString
 The other geometry to use during intersection tests .
 Returns
 list of list of tuple of number
 All intersection points . One list per pair of consecutive start
 and end point , i . e . ` N - 1 ` lists of ` N ` points . Each list may
 be empty or may contain multiple points ."""

implementation:
import shapely . geometry
geom = _convert_var_to_shapely_geometry ( other )
result = [ ]
for p_start , p_end in zip ( self . coords [ : - 1 ] , self . coords [ 1 : ] ) :
    ls = shapely . geometry . LineString ( [ p_start , p_end ] )
    intersections = ls . intersection ( geom )
    intersections = list ( _flatten_shapely_collection ( intersections ) )
    intersections_points = [ ]
    for inter in intersections :
        if isinstance ( inter , shapely . geometry . linestring . LineString ) :
            inter_start = ( inter . coords [ 0 ] [ 0 ] , inter . coords [ 0 ] [ 1 ] )
            inter_end = ( inter . coords [ - 1 ] [ 0 ] , inter . coords [ - 1 ] [ 1 ] )
            intersections_points . extend ( [ inter_start , inter_end ] )
        else :
            assert isinstance ( inter , shapely . geometry . point . Point ) , ( "Expected to find shapely.geometry.point.Point or " "shapely.geometry.linestring.LineString intersection, " "actually found %s." % ( type ( inter ) , ) )
            intersections_points . append ( ( inter . x , inter . y ) )
    # sort by distance to start point , this makes it later on easier
    # to remove duplicate points
    inter_sorted = sorted ( intersections_points , key = lambda p : np . linalg . norm ( np . float32 ( p ) - p_start ) )
    result . append ( inter_sorted )
return result


signature:
def shift ( self , top = None , right = None , bottom = None , left = None ) :
    """Shift / move the line string from one or more image sides .
 Parameters
 top : None or int , optional
 Amount of pixels by which to shift the bounding box from the
 top .
 right : None or int , optional
 Amount of pixels by which to shift the bounding box from the
 right .
 bottom : None or int , optional
 Amount of pixels by which to shift the bounding box from the
 bottom .
 left : None or int , optional
 Amount of pixels by which to shift the bounding box from the
 left .
 Returns
 result : imgaug . augmentables . lines . LineString
 Shifted line string ."""

implementation:
top = top if top is not None else 0
right = right if right is not None else 0
bottom = bottom if bottom is not None else 0
left = left if left is not None else 0
coords = np . copy ( self . coords )
coords [ : , 0 ] += left - right
coords [ : , 1 ] += top - bottom
return self . copy ( coords = coords )


signature:
def draw_mask ( self , image_shape , size_lines = 1 , size_points = 0 , raise_if_out_of_image = False ) :
    """Draw this line segment as a binary image mask .
 Parameters
 image _ shape : tuple of int
 The shape of the image onto which to draw the line mask .
 size _ lines : int , optional
 Thickness of the line segments .
 size _ points : int , optional
 Size of the points in pixels .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if the line string is fully
 outside of the image . If set to False , no error will be raised and
 only the parts inside the image will be drawn .
 Returns
 ndarray
 Boolean line mask of shape ` image _ shape ` ( no channel axis ) ."""

implementation:
heatmap = self . draw_heatmap_array ( image_shape , alpha_lines = 1.0 , alpha_points = 1.0 , size_lines = size_lines , size_points = size_points , antialiased = False , raise_if_out_of_image = raise_if_out_of_image )
return heatmap > 0.5


signature:
def draw_lines_heatmap_array ( self , image_shape , alpha = 1.0 , size = 1 , antialiased = True , raise_if_out_of_image = False ) :
    """Draw the line segments of the line string as a heatmap array .
 Parameters
 image _ shape : tuple of int
 The shape of the image onto which to draw the line mask .
 alpha : float , optional
 Opacity of the line string . Higher values denote a more visible
 line string .
 size : int , optional
 Thickness of the line segments .
 antialiased : bool , optional
 Whether to draw the line with anti - aliasing activated .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if the line string is fully
 outside of the image . If set to False , no error will be raised and
 only the parts inside the image will be drawn .
 Returns
 ndarray
 Float array of shape ` image _ shape ` ( no channel axis ) with drawn
 line string . All values are in the interval ` ` [ 0.0 , 1.0 ] ` ` ."""

implementation:
assert len ( image_shape ) == 2 or ( len ( image_shape ) == 3 and image_shape [ - 1 ] == 1 ) , ( "Expected (H,W) or (H,W,1) as image_shape, got %s." % ( image_shape , ) )
arr = self . draw_lines_on_image ( np . zeros ( image_shape , dtype = np . uint8 ) , color = 255 , alpha = alpha , size = size , antialiased = antialiased , raise_if_out_of_image = raise_if_out_of_image )
return arr . astype ( np . float32 ) / 255.0


signature:
def draw_points_heatmap_array ( self , image_shape , alpha = 1.0 , size = 1 , raise_if_out_of_image = False ) :
    """Draw the points of the line string as a heatmap array .
 Parameters
 image _ shape : tuple of int
 The shape of the image onto which to draw the point mask .
 alpha : float , optional
 Opacity of the line string points . Higher values denote a more
 visible points .
 size : int , optional
 Size of the points in pixels .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if the line string is fully
 outside of the image . If set to False , no error will be raised and
 only the parts inside the image will be drawn .
 Returns
 ndarray
 Float array of shape ` image _ shape ` ( no channel axis ) with drawn
 line string points . All values are in the interval ` ` [ 0.0 , 1.0 ] ` ` ."""

implementation:
assert len ( image_shape ) == 2 or ( len ( image_shape ) == 3 and image_shape [ - 1 ] == 1 ) , ( "Expected (H,W) or (H,W,1) as image_shape, got %s." % ( image_shape , ) )
arr = self . draw_points_on_image ( np . zeros ( image_shape , dtype = np . uint8 ) , color = 255 , alpha = alpha , size = size , raise_if_out_of_image = raise_if_out_of_image )
return arr . astype ( np . float32 ) / 255.0


signature:
def draw_heatmap_array ( self , image_shape , alpha_lines = 1.0 , alpha_points = 1.0 , size_lines = 1 , size_points = 0 , antialiased = True , raise_if_out_of_image = False ) :
    """Draw the line segments and points of the line string as a heatmap array .
 Parameters
 image _ shape : tuple of int
 The shape of the image onto which to draw the line mask .
 alpha _ lines : float , optional
 Opacity of the line string . Higher values denote a more visible
 line string .
 alpha _ points : float , optional
 Opacity of the line string points . Higher values denote a more
 visible points .
 size _ lines : int , optional
 Thickness of the line segments .
 size _ points : int , optional
 Size of the points in pixels .
 antialiased : bool , optional
 Whether to draw the line with anti - aliasing activated .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if the line string is fully
 outside of the image . If set to False , no error will be raised and
 only the parts inside the image will be drawn .
 Returns
 ndarray
 Float array of shape ` image _ shape ` ( no channel axis ) with drawn
 line segments and points . All values are in the
 interval ` ` [ 0.0 , 1.0 ] ` ` ."""

implementation:
heatmap_lines = self . draw_lines_heatmap_array ( image_shape , alpha = alpha_lines , size = size_lines , antialiased = antialiased , raise_if_out_of_image = raise_if_out_of_image )
if size_points <= 0 :
    return heatmap_lines
heatmap_points = self . draw_points_heatmap_array ( image_shape , alpha = alpha_points , size = size_points , raise_if_out_of_image = raise_if_out_of_image )
heatmap = np . dstack ( [ heatmap_lines , heatmap_points ] )
return np . max ( heatmap , axis = 2 )


signature:
def draw_lines_on_image ( self , image , color = ( 0 , 255 , 0 ) , alpha = 1.0 , size = 3 , antialiased = True , raise_if_out_of_image = False ) :
    """Draw the line segments of the line string on a given image .
 Parameters
 image : ndarray or tuple of int
 The image onto which to draw .
 Expected to be ` ` uint8 ` ` and of shape ` ` ( H , W , C ) ` ` with ` ` C ` `
 usually being ` ` 3 ` ` ( other values are not tested ) .
 If a tuple , expected to be ` ` ( H , W , C ) ` ` and will lead to a new
 ` ` uint8 ` ` array of zeros being created .
 color : int or iterable of int
 Color to use as RGB , i . e . three values .
 alpha : float , optional
 Opacity of the line string . Higher values denote a more visible
 line string .
 size : int , optional
 Thickness of the line segments .
 antialiased : bool , optional
 Whether to draw the line with anti - aliasing activated .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if the line string is fully
 outside of the image . If set to False , no error will be raised and
 only the parts inside the image will be drawn .
 Returns
 ndarray
 ` image ` with line drawn on it ."""

implementation:
from . . import dtypes as iadt
from . . augmenters import blend as blendlib
image_was_empty = False
if isinstance ( image , tuple ) :
    image_was_empty = True
    image = np . zeros ( image , dtype = np . uint8 )
assert image . ndim in [ 2 , 3 ] , ( ( "Expected image or shape of form (H,W) or (H,W,C), " + "got shape %s." ) % ( image . shape , ) )
if len ( self . coords ) <= 1 or alpha < 0 + 1e-4 or size < 1 :
    return np . copy ( image )
if raise_if_out_of_image and self . is_out_of_image ( image , partly = False , fully = True ) :
    raise Exception ( "Cannot draw line string '%s' on image with shape %s, because " "it would be out of bounds." % ( self . __str__ ( ) , image . shape ) )
if image . ndim == 2 :
    assert ia . is_single_number ( color ) , ( "Got a 2D image. Expected then 'color' to be a single number, " "but got %s." % ( str ( color ) , ) )
    color = [ color ]
elif image . ndim == 3 and ia . is_single_number ( color ) :
    color = [ color ] * image . shape [ - 1 ]
image = image . astype ( np . float32 )
height , width = image . shape [ 0 : 2 ]
# We can ' t trivially exclude lines outside of the image here , because
# even if start and end point are outside , there can still be parts of
# the line inside the image .
# TODO Do this with edge - wise intersection tests
lines = [ ]
for line_start , line_end in zip ( self . coords [ : - 1 ] , self . coords [ 1 : ] ) : # note that line ( ) expects order ( y1 , x1 , y2 , x2 ) , hence ( [ 1 ] , [ 0 ] )
    lines . append ( ( line_start [ 1 ] , line_start [ 0 ] , line_end [ 1 ] , line_end [ 0 ] ) )
# skimage . draw . line can only handle integers
lines = np . round ( np . float32 ( lines ) ) . astype ( np . int32 )
# size = = 0 is already covered above
# Note here that we have to be careful not to draw lines two times
# at their intersection points , e . g . for ( p0 , p1 ) , ( p1 , 2 ) we could
# end up drawing at p1 twice , leading to higher values if alpha is used .
color = np . float32 ( color )
heatmap = np . zeros ( image . shape [ 0 : 2 ] , dtype = np . float32 )
for line in lines :
    if antialiased :
        rr , cc , val = skimage . draw . line_aa ( * line )
    else :
        rr , cc = skimage . draw . line ( * line )
        val = 1.0
    # mask check here , because line ( ) can generate coordinates
    # outside of the image plane
    rr_mask = np . logical_and ( 0 <= rr , rr < height )
    cc_mask = np . logical_and ( 0 <= cc , cc < width )
    mask = np . logical_and ( rr_mask , cc_mask )
    if np . any ( mask ) :
        rr = rr [ mask ]
        cc = cc [ mask ]
        val = val [ mask ] if not ia . is_single_number ( val ) else val
        heatmap [ rr , cc ] = val * alpha
if size > 1 :
    kernel = np . ones ( ( size , size ) , dtype = np . uint8 )
    heatmap = cv2 . dilate ( heatmap , kernel )
if image_was_empty :
    image_blend = image + heatmap * color
else :
    image_color_shape = image . shape [ 0 : 2 ]
    if image . ndim == 3 :
        image_color_shape = image_color_shape + ( 1 , )
    image_color = np . tile ( color , image_color_shape )
    image_blend = blendlib . blend_alpha ( image_color , image , heatmap )
image_blend = iadt . restore_dtypes_ ( image_blend , np . uint8 )
return image_blend


signature:
def draw_points_on_image ( self , image , color = ( 0 , 128 , 0 ) , alpha = 1.0 , size = 3 , copy = True , raise_if_out_of_image = False ) :
    """Draw the points of the line string on a given image .
 Parameters
 image : ndarray or tuple of int
 The image onto which to draw .
 Expected to be ` ` uint8 ` ` and of shape ` ` ( H , W , C ) ` ` with ` ` C ` `
 usually being ` ` 3 ` ` ( other values are not tested ) .
 If a tuple , expected to be ` ` ( H , W , C ) ` ` and will lead to a new
 ` ` uint8 ` ` array of zeros being created .
 color : iterable of int
 Color to use as RGB , i . e . three values .
 alpha : float , optional
 Opacity of the line string points . Higher values denote a more
 visible points .
 size : int , optional
 Size of the points in pixels .
 copy : bool , optional
 Whether it is allowed to draw directly in the input
 array ( ` ` False ` ` ) or it has to be copied ( ` ` True ` ` ) .
 The routine may still have to copy , even if ` ` copy = False ` ` was
 used . Always use the return value .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if the line string is fully
 outside of the image . If set to False , no error will be raised and
 only the parts inside the image will be drawn .
 Returns
 ndarray
 Float array of shape ` image _ shape ` ( no channel axis ) with drawn
 line string points . All values are in the interval ` ` [ 0.0 , 1.0 ] ` ` ."""

implementation:
from . kps import KeypointsOnImage
kpsoi = KeypointsOnImage . from_xy_array ( self . coords , shape = image . shape )
image = kpsoi . draw_on_image ( image , color = color , alpha = alpha , size = size , copy = copy , raise_if_out_of_image = raise_if_out_of_image )
return image


signature:
def draw_on_image ( self , image , color = ( 0 , 255 , 0 ) , color_lines = None , color_points = None , alpha = 1.0 , alpha_lines = None , alpha_points = None , size = 1 , size_lines = None , size_points = None , antialiased = True , raise_if_out_of_image = False ) :
    """Draw the line string on an image .
 Parameters
 image : ndarray
 The ` ( H , W , C ) ` ` uint8 ` image onto which to draw the line string .
 color : iterable of int , optional
 Color to use as RGB , i . e . three values .
 The color of the line and points are derived from this value ,
 unless they are set .
 color _ lines : None or iterable of int
 Color to use for the line segments as RGB , i . e . three values .
 If ` ` None ` ` , this value is derived from ` color ` .
 color _ points : None or iterable of int
 Color to use for the points as RGB , i . e . three values .
 If ` ` None ` ` , this value is derived from ` ` 0.5 * color ` ` .
 alpha : float , optional
 Opacity of the line string . Higher values denote more visible
 points .
 The alphas of the line and points are derived from this value ,
 unless they are set .
 alpha _ lines : None or float , optional
 Opacity of the line string . Higher values denote more visible
 line string .
 If ` ` None ` ` , this value is derived from ` alpha ` .
 alpha _ points : None or float , optional
 Opacity of the line string points . Higher values denote more
 visible points .
 If ` ` None ` ` , this value is derived from ` alpha ` .
 size : int , optional
 Size of the line string .
 The sizes of the line and points are derived from this value ,
 unless they are set .
 size _ lines : None or int , optional
 Thickness of the line segments .
 If ` ` None ` ` , this value is derived from ` size ` .
 size _ points : None or int , optional
 Size of the points in pixels .
 If ` ` None ` ` , this value is derived from ` ` 3 * size ` ` .
 antialiased : bool , optional
 Whether to draw the line with anti - aliasing activated .
 This does currently not affect the point drawing .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if the line string is fully
 outside of the image . If set to False , no error will be raised and
 only the parts inside the image will be drawn .
 Returns
 ndarray
 Image with line string drawn on it ."""

implementation:
assert color is not None
assert alpha is not None
assert size is not None
color_lines = color_lines if color_lines is not None else np . float32 ( color )
color_points = color_points if color_points is not None else np . float32 ( color ) * 0.5
alpha_lines = alpha_lines if alpha_lines is not None else np . float32 ( alpha )
alpha_points = alpha_points if alpha_points is not None else np . float32 ( alpha )
size_lines = size_lines if size_lines is not None else size
size_points = size_points if size_points is not None else size * 3
image = self . draw_lines_on_image ( image , color = np . array ( color_lines ) . astype ( np . uint8 ) , alpha = alpha_lines , size = size_lines , antialiased = antialiased , raise_if_out_of_image = raise_if_out_of_image )
image = self . draw_points_on_image ( image , color = np . array ( color_points ) . astype ( np . uint8 ) , alpha = alpha_points , size = size_points , copy = False , raise_if_out_of_image = raise_if_out_of_image )
return image