简体   繁体   中英

How can I index numpy arrays with a list of ranges?

I'm extracting pixel values from a series of 148 time series images to get some information about fluorescent values. The regions of interest in each image are defined by a series of coordinates of different lengths eg region 1 (which exists in all of the 148 images) are defined by 175 coordinates whereas region 2 is defined by 107 coordinates. my issues is that I have come to a point where I have a numpy array with a length of 148, and each of these 148 arrays contain 11,000 pixel values. I want to subset each of these arrays with 11,000 with the different coordinate ranges. Because the coordinate ranges are different and the arrays can't be split evenly it's really hard to get it to work. This is what I have so far:

# define a function to find out the lengths of each ROI coordinate lists: 

def number_of_coordinates_to_define_each_region(coordinates):
    length = []
    for arrays in coordinates:
        leng = len(arrays)
        length.append(leng)
    return length

coordinate_length = number_of_coordinates_to_define_each_region(coords)
print(coordinate_length)

OUT: [175, 107, 107, 95, 67, 106, 836, 74, 1054, 101, 72, 93, 181, 223, 671, 288, 123, 69, 121, 175, 317, 325, 189, 139, 494, 296, 244, 129, 282, 226, 236, 108, 134, 284, 117, 144, 97, 95, 193, 255, 182, 191, 285, 104, 91, 255, 60, 112, 142, 189, 73, 81, 133, 65, 148]

# these represent 55 regions of interest each with the associated number of coordinates

# function to make the coordinate lists ranges instead of single numbers 

def list_of_coordinate_ranges(coordinate_length):
    items = []
    for x in coordinate_length:
        item = range(x)
        items.append(item)
    return items

coordinate_arrays = list_of_coordinate_ranges(coordinate_length)
print(coordinate_arrays)

OUT: [range(0, 175), range(0, 107), range(0, 107), range(0, 95), range(0, 67), range(0, 106), range(0, 836), range(0, 74), range(0, 1054), range(0, 101), range(0, 72), range(0, 93), range(0, 181), range(0, 223), range(0, 671), range(0, 288), range(0, 123), range(0, 69), range(0, 121), range(0, 175), range(0, 317), range(0, 325), range(0, 189), range(0, 139), range(0, 494), range(0, 296), range(0, 244), range(0, 129), range(0, 282), range(0, 226), range(0, 236), range(0, 108), range(0, 134), range(0, 284), range(0, 117), range(0, 144), range(0, 97), range(0, 95), range(0, 193), range(0, 255), range(0, 182), range(0, 191), range(0, 285), range(0, 104), range(0, 91), range(0, 255), range(0, 60), range(0, 112), range(0, 142), range(0, 189), range(0, 73), range(0, 81), range(0, 133), range(0, 65), range(0, 148)]

# turn the list of pixel values into a numpy array and split 148 times to separate out into different images

pixel_collection = np.array(pixels)
pixel_collection_2 = np.split(pixel_collection, 148)

split_collection = []
for number in range(148):
    item_1 = pixel_collection_2[number]
    split_collection.append(item_1)

# subset each image with the ranges of coordinates

mean_pixels = []
for arrays in split_collection:
    for x in coordinate_arrays:
        items_2 = np.mean(arrays[x])
        mean_pixels.append(items_2)

I wont post the output but it basically gives me the mean pixels of each range but starts from index 0 each time rather than subsetting by 175, then subsetting by 107 AFTER the 175.

So my question is how can I subset the arrays with the ranges but make it do it in a sequence rather than starting from the beginning each time?

Sorry for the long question!

To simply things, I will assume we have only 5 frames with 10 pixels each. Since you are saying you have this as a 1D list, I will just start with np.arange() . This will give us some dummy data for demonstration:

pixels = np.arange(50)

First, instead of using np.split() to get a list of array, we can just reshape pixels

pixels = pixels.reshape((5, 10))

Now let us assume the regions of interest (for the 10 pixels of each frame) are the indices 0-3, 4-5 and 6-9. Since they all are consecutive, we only need to specify the position where next region starts:

split_indices = [4, 6]

You already used np.split() , but if you pass a list of integers as the second argument, it will give you exactly those subsections. Additionally, the axis along with the array has to be split needs to be specified:

splits = np.split(pixels, split_indices, axis=1)

Finally, we can just iterate over those splits and calculate the mean:

mean_pixels = [s.mean(axis=1) for s in splits]

We now have a list of arrays, with the average pixel value of each region in each frame. We may stack this into a single array, which looks better when printed:

mean_pixels = np.stack(mean_pixels)
print(mean_pixels.T)    # transpose to have each row represent one frame
# array([[ 1.5,  4.5,  7.5],
#        [11.5, 14.5, 17.5],
#        [21.5, 24.5, 27.5],
#        [31.5, 34.5, 37.5],
#        [41.5, 44.5, 47.5]])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM