Placement sets

PlacementSets are constructed from the bsb.storage.Storage and can be used to retrieve the positions, morphologies, rotations and additional datasets.

Note

Loading datasets from storage is an expensive operation. Store a local reference to the data you retrieve instead of making multiple calls.

Retrieving a PlacementSet

Multiple get_placement_set methods exist in several places as shortcuts to access the same PlacementSet object. If the placement set does not exist, a DatesetNotFoundError is thrown.

from bsb import from_storage

scaffold = from_storage("my_network.hdf5")
ps = scaffold.get_placement_set("my_cell")
# Alternatives to obtain the same placement set:
ps = scaffold.get_placement_set(network.cell_types.my_cell)
ps = scaffold.cell_types.my_cell.get_placement_set()

print(ps.tag)  # Name of the placement set

Identifiers

Cells have no global identifiers, instead you use the indices of their data, i.e. the n-th position belongs to cell n, and so will the n-th rotation. To easily retrieve the cells’ IDs make use of the method load_ids.

list_of_ids = ps.load_ids()

Positions

The positions of the cells can be retrieved using the load_positions method.

for n, position in enumerate(ps.load_positions()):
  print(f"Cell {n}, position: {pos}")

Morphologies

The morphology of the cells can be retrieved using the load_morphologies method.

for n, (pos, morpho) in enumerate(zip(ps.load_positions(), ps.load_morphologies())):
  print(f"Cell {n}, position: {pos}, morpho: {morpho}")

Warning

Loading morphologies is especially expensive.
There are better ways to iterate over it using either soft caching or hard caching.

Rotations

The positions of the cells can be retrieved using the load_rotations method.

for n, rotation in enumerate(ps.load_rotations()):
  print(f"Cell {n}, rotation: ", rotation)

Chunk filtering

You can use a list of Chunks to subsample the cells present within them. This can be done when you generate the PlacementSet object with on of the function get_placement_set or using the set_chunk_filter method.

Important

Note that the ids of the placement set will be remapped according to the Chunk filter

from bsb import Chunk

# we suppose here a case where 10 `my_cell` cells are placed in two Chunks
# 7 in the Chunk [0, 0, 0]
# 3 in the Chunk [0, 0, 1]
ps = scaffold.get_placement_set(
        "my_cell",
        chunks=[Chunk([0, 0, 0], chunk_size=100)]
)
print(ps.get_all_chunks())  # should print Chunk([0, 0, 0])
print(ps.load_ids())  # should print [0, 1, 2, 3, 4, 5, 6]
ps.set_chunk_filter([Chunk([0, 0, 1], chunk_size=100)])
print(ps.get_all_chunks())  # should print Chunk([0, 0, 1])
print(ps.load_ids())  # should print [0, 1, 2]
ps.set_chunk_filter([])  # reset chunk filter
print(ps.load_ids())  # should print [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Labeling

You can label cells using the label or the label_by_mask methods. These functions are almost identical. The first one uses cell ids while the other needs a boolean mask array.

Note

Labeling is cumulative, i.e., if you relabel a cell then the new labels will be added to the previous ones. You can remove labels previously put, using the remove_labels or remove_labels_by_mask functions.

# Assuming ps has 7 cells
print(ps.load_ids())  # prints [0, 1, 2, 3, 4, 5, 6]
# you can put as many labels onto one cell
ps.label(["labelA", "labelB"], [1, 5, 6])
# the boolean mask array should be the same size as the ps
ps.label_by_mask(["labelC"], [True, True, False, True, False, True, False])
# we overwrite the previous labels
ps.remove_labels(["labelA", "labelB", "labelC"], [1])
ps.label(["labelD"], [1])

You can retrieve the cells labelled leveraging the get_labelled or the get_label_mask methods. These functions are the counterpart of the label and label_by_mask functions: one returns the list of ids labelled while the other provides a boolean mask array. Finally, you can retrieve the list of unique label sets that is attached to each cell with the method get_unique_labels .

Note

If you provide None as labels to these functions, they would return all ps ids. You should provide an empty list to filter non labelled cells.

Note

The function will return cells labelled by any of the labels provided.

# reusing previous example
print(ps.get_labelled(["labelA"]))  # should print [5, 6]
print(ps.get_label_mask(["labelC"]))  # should print [True, False, False, True, False, True, False]
print(ps.get_labelled(["labelB", "labelC"])) # should print [0, 3, 5, 6]
print(ps.get_labelled(["labelD"]))  # should print [1]
print(ps.get_label_mask())  # should print [True, True, True, True, True, True, True]
print(ps.get_labelled([]))  # should print [2, 4]
# should print [set(), {"labelA", "labelB"}, {"labelC"}, {"labelA", "labelB", "labelC"}, {"labelD"}]
print(ps.get_unique_labels())

You can also filter your PlacementSet according to the labels used setting the label_filter`s (getter: :meth:`get_label_filter <bsb:bsb.storage.interfaces.PlacementSet.get_label_filter> setter: set_label_filter). This means that the length of the PlacementSet and all its attached datasets (ids, rotations, morphologies) will be sub-sampled according to the label filter.

Similar to the previous function, this filter returns cells matching any of the labels provided.

Important

Unlike the Chunk filtering, the PlacementSet ids do not change with the labels filter.

Note

You can also filter cell labels when you retrieve the PlacementSet with the function get_placement_set.

# reusing previous example
ps.set_label_filter(["labelA"])
print(ps.load_ids())  # should print [5, 6]
print(len(ps))  # should print 2
ps.set_label_filter(["labelB", "labelC"])
print(ps.load_ids())  # should print [0, 3, 5, 6]
ps.set_label_filter([])  # filter cells that are not labelled
print(ps.load_ids()) # should print [2, 4]
ps.set_label_filter(None)  # reset label filtering
print(ps.load_ids()) # should print [0, 1, 2, 3, 4, 5, 6]

Important

If you want to label the PlacementSet again after filtering it, you have to use indexes corresponding to its new length.

# reusing previous example
ps.set_label_filter(["labelA"])
print(ps.load_ids())  # should print [5, 6]
# So to label cell 6, we use its new index: 1
ps.label(["labelE"], [1])  # will add label "labelE" to cell 6
print(ps.get_labelled(["labelE"]))  # should print [6]

Morphology filtering

Similar to the general cell labelling, you can use morphology labels (ie. labels assigned to morphology points, see also this page) to filter the morphologies sections that you want to isolate in your ps.

Note

You can also filter morphology labels when you retrieve the PlacementSet with the function get_placement_set.

ps.set_morphology_label_filter(["dendrites", "apical_dendrites"])

Additional datasets

Not implemented yet.