# Buggy code
def _data_bytes_to_shaped_array(
    data_bytes, lbpack, boundary_packing, data_shape, data_type, mdi, mask=None
):
    """
    Convert the already read binary data payload into a numpy array, unpacking
    and decompressing as per the F3 specification.

    """
    if lbpack.n1 in (0, 2):
        data = np.frombuffer(data_bytes, dtype=data_type)
    elif lbpack.n1 == 1:
        if mo_pack is not None:
            try:
                decompress_wgdos = mo_pack.decompress_wgdos
            except AttributeError:
                decompress_wgdos = mo_pack.unpack_wgdos
        else:
            msg = (
                "Unpacking PP fields with LBPACK of {} "
                "requires mo_pack to be installed".format(lbpack.n1)
            )
            raise ValueError(msg)
        data = decompress_wgdos(data_bytes, data_shape[0], data_shape[1], mdi)
    elif lbpack.n1 == 4:
        if mo_pack is not None and hasattr(mo_pack, "decompress_rle"):
            decompress_rle = mo_pack.decompress_rle
        else:
            msg = (
                "Unpacking PP fields with LBPACK of {} "
                "requires mo_pack to be installed".format(lbpack.n1)
            )
            raise ValueError(msg)
        data = decompress_rle(data_bytes, data_shape[0], data_shape[1], mdi)
    else:
        raise iris.exceptions.NotYetImplementedError(
            "PP fields with LBPACK of %s are not yet supported." % lbpack
        )

    # Ensure we have a writeable data buffer.
    # NOTE: "data.setflags(write=True)" is not valid for numpy >= 1.16.0.
    if not data.flags["WRITEABLE"]:
        data = data.copy()

    # Ensure the data is in the native byte order
    if not data.dtype.isnative:
        data.byteswap(True)
        data.dtype = data.dtype.newbyteorder("=")

    if boundary_packing is not None:
        # Convert a long string of numbers into a "lateral boundary
        # condition" array, which is split into 4 quartiles, North
        # East, South, West and where North and South contain the corners.
        compressed_data = data
        data = np.ma.masked_all(data_shape)
        data.fill_value = mdi

        boundary_height = boundary_packing.y_halo + boundary_packing.rim_width
        boundary_width = boundary_packing.x_halo + boundary_packing.rim_width
        y_height, x_width = data_shape
        # The height of the east and west components.
        mid_height = y_height - 2 * boundary_height

        n_s_shape = boundary_height, x_width
        e_w_shape = mid_height, boundary_width

        # Keep track of our current position in the array.
        current_posn = 0

        north = compressed_data[: boundary_height * x_width]
        current_posn += len(north)
        data[-boundary_height:, :] = north.reshape(*n_s_shape)

        east = compressed_data[
            current_posn : current_posn + boundary_width * mid_height
        ]
        current_posn += len(east)
        data[boundary_height:-boundary_height, -boundary_width:] = east.reshape(
            *e_w_shape
        )

        south = compressed_data[current_posn : current_posn + boundary_height * x_width]
        current_posn += len(south)
        data[:boundary_height, :] = south.reshape(*n_s_shape)

        west = compressed_data[
            current_posn : current_posn + boundary_width * mid_height
        ]
        current_posn += len(west)
        data[boundary_height:-boundary_height, :boundary_width] = west.reshape(
            *e_w_shape
        )

    elif lbpack.n2 == 2:
        if mask is None:
            raise ValueError("No mask was found to unpack the data. Could not load.")
        land_mask = mask.data.astype(np.bool)
        sea_mask = ~land_mask
        new_data = np.ma.masked_all(land_mask.shape)
        new_data.fill_value = mdi
        if lbpack.n3 == 1:
            # Land mask packed data.
            # Sometimes the data comes in longer than it should be (i.e. it
            # looks like the compressed data is compressed, but the trailing
            # data hasn't been clipped off!).
            new_data[land_mask] = data[: land_mask.sum()]
        elif lbpack.n3 == 2:
            # Sea mask packed data.
            new_data[sea_mask] = data[: sea_mask.sum()]
        else:
            raise ValueError("Unsupported mask compression.")
        data = new_data

    else:
        # Reform in row-column order
        data.shape = data_shape

    # Mask the array
    if mdi in data:
        data = ma.masked_values(data, mdi, copy=False)

    return data


# Traceback (thread.error)
Traceback (most recent call last):
File "/.../create_jules_ic_v2.py", line 279, in <module>
main()
File "/.../create_jules_ic_v2.py", line 274, in main
nameoffile=create_jules_ic(Ddate,INDIR,UM_FILE_IN,OUTDIR)
File "/.../create_jules_ic_v2.py", line 152, in create_jules_ic
print(type(cube_vegfrac.data <=0.0001))
File "/.../python2.7/site-packages/iris/cube.py", line 1644, in data
return self._data_manager.data
File "/.../python2.7/site-packages/iris/_data_manager.py", line 216, in data
result = as_concrete_data(self._lazy_array)
File "/.../python2.7/site-packages/iris/_lazy_data.py", line 128, in as_concrete_data
data = np.asanyarray(data.compute())
File "/.../python2.7/site-packages/dask/base.py", line 143, in compute
(result,) = compute(self, traverse=False, **kwargs)
File "/.../python2.7/site-packages/dask/base.py", line 392, in compute
results = get(dsk, keys, **kwargs)
File "/.../python2.7/site-packages/dask/threaded.py", line 75, in get
pack_exception=pack_exception, **kwargs)
File "/.../python2.7/site-packages/dask/local.py", line 521, in get_async
raise_exception(exc, tb)
File "/.../python2.7/site-packages/dask/local.py", line 290, in execute_task
result = _execute_task(task, data)
File "/.../python2.7/site-packages/dask/local.py", line 270, in _execute_task
args2 = [_execute_task(a, cache) for a in args]
File "/.../python2.7/site-packages/dask/local.py", line 271, in _execute_task
return func(*args2)
File "/.../python2.7/site-packages/dask/array/core.py", line 74, in getter
c = a[b]
File "/.../python2.7/site-packages/iris/fileformats/pp.py", line 647, in __getitem__
self.mdi, self.mask)
File "/.../python2.7/site-packages/iris/fileformats/pp.py", line 770, in _data_bytes_to_shaped_array
land_mask = mask.data.astype(np.bool)
File "/.../python2.7/site-packages/iris/fileformats/pp.py", line 1033, in data
self._data = as_concrete_data(self._data)
File "/.../python2.7/site-packages/iris/_lazy_data.py", line 128, in as_concrete_data
data = np.asanyarray(data.compute())
File "/.../python2.7/site-packages/dask/base.py", line 143, in compute
(result,) = compute(self, traverse=False, **kwargs)
File "/.../python2.7/site-packages/dask/base.py", line 392, in compute
results = get(dsk, keys, **kwargs)
File "/.../python2.7/site-packages/dask/threaded.py", line 70, in get
pool = ThreadPool(num_workers)
File "/.../python2.7/multiprocessing/pool.py", line 727, in __init__
Pool.__init__(self, processes, initializer, initargs)
File "/.../python2.7/multiprocessing/pool.py", line 159, in __init__
self._repopulate_pool()
File "/.../python2.7/multiprocessing/pool.py", line 223, in _repopulate_pool
w.start()
File "/.../python2.7/multiprocessing/dummy/__init__.py", line 75, in start
threading.Thread.start(self)
File "/.../python2.7/threading.py", line 736, in start
_start_new_thread(self.__bootstrap, ())
thread.error: can't start new thread

# Fixed code
def _data_bytes_to_shaped_array(
    data_bytes, lbpack, boundary_packing, data_shape, data_type, mdi, mask=None
):
    """
    Convert the already read binary data payload into a numpy array, unpacking
    and decompressing as per the F3 specification.

    """
    if lbpack.n1 in (0, 2):
        data = np.frombuffer(data_bytes, dtype=data_type)
    elif lbpack.n1 == 1:
        if mo_pack is not None:
            try:
                decompress_wgdos = mo_pack.decompress_wgdos
            except AttributeError:
                decompress_wgdos = mo_pack.unpack_wgdos
        else:
            msg = (
                "Unpacking PP fields with LBPACK of {} "
                "requires mo_pack to be installed".format(lbpack.n1)
            )
            raise ValueError(msg)
        data = decompress_wgdos(data_bytes, data_shape[0], data_shape[1], mdi)
    elif lbpack.n1 == 4:
        if mo_pack is not None and hasattr(mo_pack, "decompress_rle"):
            decompress_rle = mo_pack.decompress_rle
        else:
            msg = (
                "Unpacking PP fields with LBPACK of {} "
                "requires mo_pack to be installed".format(lbpack.n1)
            )
            raise ValueError(msg)
        data = decompress_rle(data_bytes, data_shape[0], data_shape[1], mdi)
    else:
        raise iris.exceptions.NotYetImplementedError(
            "PP fields with LBPACK of %s are not yet supported." % lbpack
        )

    # Ensure we have a writeable data buffer.
    # NOTE: "data.setflags(write=True)" is not valid for numpy >= 1.16.0.
    if not data.flags["WRITEABLE"]:
        data = data.copy()

    # Ensure the data is in the native byte order
    if not data.dtype.isnative:
        data.byteswap(True)
        data.dtype = data.dtype.newbyteorder("=")

    if boundary_packing is not None:
        # Convert a long string of numbers into a "lateral boundary
        # condition" array, which is split into 4 quartiles, North
        # East, South, West and where North and South contain the corners.
        compressed_data = data
        data = np.ma.masked_all(data_shape)
        data.fill_value = mdi

        boundary_height = boundary_packing.y_halo + boundary_packing.rim_width
        boundary_width = boundary_packing.x_halo + boundary_packing.rim_width
        y_height, x_width = data_shape
        # The height of the east and west components.
        mid_height = y_height - 2 * boundary_height

        n_s_shape = boundary_height, x_width
        e_w_shape = mid_height, boundary_width

        # Keep track of our current position in the array.
        current_posn = 0

        north = compressed_data[: boundary_height * x_width]
        current_posn += len(north)
        data[-boundary_height:, :] = north.reshape(*n_s_shape)

        east = compressed_data[
            current_posn : current_posn + boundary_width * mid_height
        ]
        current_posn += len(east)
        data[boundary_height:-boundary_height, -boundary_width:] = east.reshape(
            *e_w_shape
        )

        south = compressed_data[current_posn : current_posn + boundary_height * x_width]
        current_posn += len(south)
        data[:boundary_height, :] = south.reshape(*n_s_shape)

        west = compressed_data[
            current_posn : current_posn + boundary_width * mid_height
        ]
        current_posn += len(west)
        data[boundary_height:-boundary_height, :boundary_width] = west.reshape(
            *e_w_shape
        )

    elif lbpack.n2 == 2:
        if mask is None:
            # If we are given no mask to apply, then just return raw data, even
            # though it does not have the correct shape.
            # For dask-delayed loading, this means that mask, data and the
            # combination can be properly handled within a dask graph.
            # However, we still mask any MDI values in the array (below).
            pass
        else:
            land_mask = mask.data.astype(np.bool)
            sea_mask = ~land_mask
            new_data = np.ma.masked_all(land_mask.shape)
            new_data.fill_value = mdi
            if lbpack.n3 == 1:
                # Land mask packed data.
                # Sometimes the data comes in longer than it should be (i.e. it
                # looks like the compressed data is compressed, but the
                # trailing data hasn't been clipped off!).
                new_data[land_mask] = data[: land_mask.sum()]
            elif lbpack.n3 == 2:
                # Sea mask packed data.
                new_data[sea_mask] = data[: sea_mask.sum()]
            else:
                raise ValueError("Unsupported mask compression.")
            data = new_data

    else:
        # Reform in row-column order
        data.shape = data_shape

    # Mask the array
    if mdi in data:
        data = ma.masked_values(data, mdi, copy=False)

    return data