As usual intro, I am a tyro in python. However, I got quite a big project to code. It is a surface flow model with Cell Automata. Anyway, I also want to include building roofs in my model. Imagine you have an ascii file indicating buildings with 1s, while the rest is 0. There are just those two states. Now, I want to find all adjacent cells indicating the same building and store them (or rather the information of y,x and one more (maybe elevation),so 3 columns) in an individual building arrays. Keep in mind that buildings can have all possible forms though diagonally connected cells doesn't belong to the same building. So only northern, southern, western and eastern cells can belong to the same building.
I did my homework and googled it but so far I couldn't find a satisfying answer.
example: initial land-cover array:
([0,0,0,0,0,0,0]
[0,0,1,0,0,0,0]
[0,1,1,1,0,1,1]
[0,1,0,1,0,0,1]
[0,0,0,0,0,0,0])
output(I need to now the coordinates of the cells in my initial array):
building_1=([1,2],[2,1],[2,2],[2,3],[3,1],[3,3])
building_2=([2,5],[2,6],[3,6])
Any help is greatly appreciated!
It looks like this function does exactly what you're looking for (from the numpy documentation):
Alternatively it seems like your use case requires using the returned coordinates to index arrays.
You might want to try
numpy.where
instead.You can use the
label
function fromscipy.ndimage
to identify the distinct buildings.Here's your example array, containing two buildings:
Import
label
.Apply
label
toa
. It returns two values: the array of labeled positions, and the number of distinct objects (buildings, in this case) found.To get the coordinates of a building,
np.where
can be used. For example,It returns a tuple of arrays; the
k
th array holds the coordinates of thek
th dimension. You can use, for example,np.column_stack
to combine these into an array:You might want a list of all the coordinate arrays. Here's one way to create such a list.
For convenience, first create a list of labels:
Use a list comprehension to create the list of coordinate arrays.
Now your building data is in
labels
andcoords
. For example, the first building was labeledlabels[0]
, and its coordinates are incoords[0]
:Thank you for the great answers! Here is a little correction. If you see the landcover array, I actually don't have 0 as background information but -9999 (0 is too precious for GIS people). I forgot to mention that. But thanks to machine yearning's hint, I made a work-around by assigning all -9999 with 0 through landcover = np.where(landcover > -9999, landcover, 0). After that I can use label. The actual aim was to find the lowest cell and to assign it as outlet. If somebody has a more efficient way, please let me know!
Original data set has -9999 as background information and 1 as building cells.
Here is a random digital elevation map.
I changed all -9999 entries to 0 in order to use label @thanks to machine yearning
Then I labeled distinct buildings and counting those distinctions @Warren Weckesser, the rest pretty much yours. thanks!
I am iterating over the bldg_coord list in order to determine the lowest cells which will be assigned as outlet
I sort the building array in ascending order according to the DEM information of each building cell in order to find the lowest lying building cells.
The lowest building cell will be used as roof outlet for rainwater
Here is the output. The first two columns are indices in den landcover array and the last is the number of adjacent building cells.