def _nms_TF(
            boxes, scores, iou_threshold, score_threshold, per_class_suppression, M
        ):
            # boxes is (B,N,4), in order [center_w, center_h, width, height]
            # scores is (B,N,C)
            # output shapes: (B,M,4), (B,M,C), (B,M), (B,)
            """
            this is implementation of CoreML's NMS layer
            """
            B, N, C = scores.shape

            iou_threshold = iou_threshold.astype(np.float32)
            score_threshold = score_threshold.astype(np.float32)

            # convert box ids to TF style
            center_w, center_h, width, height = np.split(
                boxes, 4, axis=-1
            )  # outs are all (B,N,1)
            y1 = center_h - 0.5 * height
            y2 = center_h + 0.5 * height
            x1 = center_w - 0.5 * width
            x2 = center_w + 0.5 * width
            boxes_tf = np.concatenate((y1, x1, y2, x2), axis=-1)  # (B,N,4)

            out1 = np.zeros((B, M, 4))
            out2 = np.zeros((B, M, C))
            out3 = -1 * np.ones((B, M))
            out4 = np.zeros((B,))

            for b in range(B):
                box_coord_matrix = boxes_tf[b, :, :]  # (N,4)
                score_vector = np.max(scores[b, :, :], axis=-1)  # (N,)
                if not per_class_suppression:
                    # this is the simple case as TF directly supports it
                    ids_g = tf.image.non_max_suppression(
                        box_coord_matrix,
                        score_vector,
                        max_output_size=M,
                        iou_threshold=iou_threshold,
                        score_threshold=score_threshold,
                    )
                    ids = ids_g.numpy()
                else:
                    # this is slightly complicated as TF does not directly support it
                    class_ids = np.argmax(scores[b, :, :], axis=-1)  # (N,)
                    sorted_score_ids = np.argsort(-score_vector)
                    box_coord_matrix2 = np.take(
                        box_coord_matrix, sorted_score_ids, axis=0
                    )
                    score_vector2 = np.take(score_vector, sorted_score_ids)
                    class_ids = np.take(class_ids, sorted_score_ids)
                    classes_seen = dict()
                    ids_intermediate = np.array([], dtype=np.int32)
                    for n in range(N):
                        if class_ids[n] in classes_seen:
                            continue
                        c = class_ids[n]
                        classes_seen[c] = True
                        current_class_ids = np.where(class_ids == c)[0]
                        if len(current_class_ids) > 0:
                            feed_in1 = np.take(
                                box_coord_matrix2, current_class_ids, axis=0
                            )
                            feed_in2 = np.take(score_vector2, current_class_ids)
                            cur_ids_g = tf.image.non_max_suppression(
                                feed_in1,
                                feed_in2,
                                max_output_size=M,
                                iou_threshold=iou_threshold,
                                score_threshold=score_threshold,
                            )
                            cur_ids = cur_ids_g.numpy()

                            from_sort_ids = np.take(current_class_ids, cur_ids)
                            ids_intermediate = np.append(
                                ids_intermediate, from_sort_ids
                            )
                    ids_intermediate.sort()
                    ids = np.take(sorted_score_ids, ids_intermediate)

                xx = len(ids)
                if xx == 0:
                    ids = np.array([np.argmax(score_vector)])
                    xx = 1
                if xx > M:
                    ids = ids[:M]
                    xx = len(ids)
                out1[b, :xx, :] = np.take(boxes[b, :, :], ids, axis=0)
                out2[b, :xx, :] = np.take(scores[b, :, :], ids, axis=0)
                out3[b, :xx] = ids
                out4[b] = xx

            return out1, out2, out3, out4

            this is implementation of CoreML's NMS layer
            
coremltools/test/neural_network/test_numpy_nn_layers.py