loompy API

作者: JeremyL | 来源:发表于2021-02-03 12:32 被阅读0次

# Creating and connecting

##Creating Loom files

创建一个loom文件,需要提供一个矩阵数据(numpy ndarray or scipy sparse matrix)和两个关于行列属性的字典(字典中,属性名是键值,numpy ndarrays是对应的值)。如果矩阵数据是N×M,行属性必需有N个元素,列属性应该有M个元素。

例,创建一个有100x100维矩阵数据以及一个行属性,一个列属性的loom文件:

import numpy as np
import loompy
filename = "test.loom"
matrix = np.arange(10000).reshape(100,100)
row_attrs = { "SomeRowAttr": np.arange(100) }
col_attrs = { "SomeColAttr": np.arange(100) }
loompy.create(filename, matrix, row_attrs, col_attrs)
import numpy as np
import loompy
import scipy.sparse as sparse
filename = "test.loom"
matrix = sparse.coo_matrix((100, 100))
row_attrs = { "SomeRowAttr": np.arange(100) }
col_attrs = { "SomeColAttr": np.arange(100) }
loompy.create(filename, matrix, row_attrs, col_attrs)

#loompy.create() 只是创建文件文件
#loompy.connect()可以连接loom文件,进行处理

  • loompy.new()可以创建一个空的loom文件,并且返回与loom文件之间的链接,然后就可以向文件中填充数据。
    for sample in samples:
        with loompy.connect(sample) as dsin:
            logging.info(f"Appending {sample}.")
            dsout.add_columns(ds.layers, col_attrs=dsin.col_attrs, row_attrs=dsin.row_attrs)
  • loompy.combine()根据一个已经存在的loom文件创建新的loom文件。新的内容写进去之后会根据列的维度进行填充,所以新内容和源文件内容应该有一样行数;如果对应的行的顺序不一致,可以通过添加参数Key进行调整。
loompy.combine(files, output_filename, key="Accession")
  • loompy.create_from_cellranger()导入10X Genomics cellranger结果
loompy.create_from_cellranger(folder, output_filename)

##Connecting to Loom files

#loompy.connect()可以创建loom文件的链接,不会直接读入文件;因此,就算文件特别大也不影响其速度。

  • 可以使用一个with语句来处理连接:
with loompy.connect("filename.loom") as ds:
  # do something with ds

#with会自动关闭文件,不使用with的时候,你需要自行关闭

ds = loompy.connect("filename.loom")
ds.close()

#Manipulate data

##Shape, indexing and slicing

>>> ds.shape
(100, 2345)

#loom matrix中数据可以通过索引和切片进行获取。

  • Indices: anything that can be converted to a Python long
  • Slices (i.e. : or 0:10)
  • Lists of the rows/columns you want (i.e. [0, 34, 576])
  • Mask arrays (i.e. numpy array of bool indicating the rows/columns you want)
ds[0:10, 0:10]    # Return the 10x10 submatrix starting at row and column zero
ds[99, :]         # Return the 100th row
ds[:, 99]         # Return the 100th column
ds[[0,3,5], :]    # Return rows with index 0, 3 and 5
ds[:, bool_array] # Return columns where bool_array elements are True

#提示:一次选取太多的行或者列,速度会很慢,这是由于h5py造成的。当然,如果你把整个文件读入到内存中,不存在这个问题。还有一种选择,可以使用LoomConnection.scan(),当随机选取的列或者行超过数据1%时,它会很快。

## ##Sparse data

不同层的数据都是以块的方式存放,有助于数据储存和读取;不同层的数据都可以赋于新的稠密或者稀疏矩阵数据,

  • 可以导入主矩阵或者任意层的数据,返回稀疏矩阵
ds.layers["exons"].sparse()  # Returns a scipy.sparse.coo_matrix
ds.layers["unspliced"].sparse(rows, cols)  # Returns only the indicated rows and columns (ndarrays of integers or bools)
  • 给层非陪数据
ds.layers["exons"] = my_sparse_matrix

## ##Modifying layers

修改不同层的数据,直接索引数重新进行赋值就可以了。

ds[:, :] = newdata         # Assign a full matrix
ds[3, 500] = 31            # Set the element at (3, 500) to the value 31
ds[99, :] = rowdata        # Assign new values to row with index 99
ds[:, 99] = coldata        # Assign new values to column with index 99

## ##Global attributes

全局属性使用.attrs.访问,通过赋值创建新的属性,del可以删除属性

>>> ds.attrs.title
"The title of the dataset"

>>> ds.attrs.title = "New title"
>>> ds.attrs["title"]
"New title"

>>> del ds.attrs.title

loom的属性可以像字典一样遍历处理

>>> ds.attrs.keys()
["title", "description"]

>>> for key, value in ds.attrs.items():
>>>   print(f"{key} = {value}")
title = New title
description = Fancy dataset

#全局属性可以是标量或任意形状的多维数组,元素可以是整数、浮点数或字符串。

##Row and column attributes

  • 行和列属性是分别通过ds.rads.ca访问的。
ds.ca.keys()       # Return list of column attribute names
ds.ra.Gene = ...   # Create or replace the Gene attribute
a = ds.ra.Gene     # Assign the array of gene names (assuming the attribute exists)
del ds.ra.Gene     # Delete the Gene row attribute
  • 属性也可以通过索引来访问:
a = ds.ra["Gene"]     # Assign the array of gene names (assuming the attribute exists)
del ds.ra["Gene"]     # Delete the Gene row attribute
  • 你可以将多个具有相同类型的属性提取到一个numpy数组中
a = ds.ra["Gene", "Attribute"]     # Returns a 2D array of shape (n_genes, 2)
b = ds.ca["PCA1", "PCA2"]          # Returns a 2D array of shape (n_cells, 2)
  • 访问多个属性
a = ds.ra["Gene", "GeneName"]     # Return one or the other (if only one exists)
b = ds.ca["TSNE", "PCA", "UMAP"]  # Return the one that exists (if only one exists)
  • 使用属性来模糊索引主矩阵,在选择子数组时可以使用非常紧凑和可读的语法:
array([[  2.,   9.,   9., ...,   0.,  14.,   0.]], dtype=float32)

>>> ds[(ds.ra.Gene == "Actb") | (ds.ra.Gene == "Gapdh"), :]
array([[  2.,   9.,   9., ...,   0.,  14.,   0.],
       [  0.,   1.,   4., ...,   0.,  14.,   3.]], dtype=float32)

>>> ds[:, ds.ca.CellID == "AAACATACATTCTC-1"]
array([[ 0.],
       [ 0.],
       [ 0.],
       ...,
       [ 0.],
       [ 0.],
       [ 0.]], dtype=float32)

#可以使用位运算符,| for ‘or’, & for ‘and’ and ~ for ‘not’。

(a == b) & (a > c) | ~(c <= b)

##Modifying attributes

与层不同,属性总是只能完整地读写。因此,给切片赋值不会修改磁盘上储存的属性内容。要为一个属性赋予新值,必须为该属性赋值一个完整的列表或ndarray:

with loompy.connect("filename.loom") as ds:
  ds.ca.ClusterNames = values  # where values is a list or ndarray with one element per column
  # This does not change the attribute on disk:
  ds.ca.ClusterNames[10] = "banana"

##Adding columns

  • 您可以向现有的loom文件添加列。添加行或删除矩阵的任何部分无法操作。
ds.add_columns(submatrix, col_attrs)
  • 如果要向空文件添加列,还必须提供行属性:
ds.add_columns(submatrix, col_attrs, row_attrs={"Gene": genes})
  • 你也可以添加另一个.loom文件的内容:other_file添加到ds中
ds.add_loom(other_file, key="Gene")

#注:other_file和ds应该有一样的行数,在列的维度进行合并,如果行的顺序不一致,可以通过参数key进行重排,缺失值可以自动通过fill_values填充。如果文件包含任何具有冲突值的全局属性,则可以通过将convert_attrs=True传递给该方法来自动将这些属性转换为列属性。

##Layers

loom支持多层, 每个loom只有一个的主矩阵,但可以有一个或多个具有相同行数和列数的额外层。使用LoomConnection对象上的Layers属性访问层。

  • 层支持与属性相同的python API:
ds.layers.keys()            # Return list of layers
ds.layers["unspliced"]      # Return the layer named "unspliced"
ds.layers["spliced"] = ...  # Create or replace the "spliced" layer
a = ds.layers["spliced"][:, 10] # Assign the 10th column of layer "spliced" to the variable a
del ds.layers["spliced"]     # Delete the "spliced" layer

#主矩阵也可以通过“”进行访问(类似使用层名);但是不能删除主矩阵,其它层的方法也适用于主矩阵。

  • 为了方便起见,层也可以直接在连接对象上使用。
ds["spliced"] = ...  # Create or replace the "spliced" layer
a = ds["spliced"][:, 10] # Assign the 10th column of layer "spliced" to the variable a
del ds["spliced"]     # Delete the "spliced" layer
  • 有时您可能需要创建一个空层(全部为零),以便稍后填充。空层是通过为层名指定类型来创建的。例如:
ds["empty_floats"] = "float32"
ds["empty_ints"] = "int64"

##Graphs

Loom支持以行或列作为节点的稀疏图。例如,细胞的稀疏图(存储在列中)可以表示细胞的KNN图。在这种情况下,细胞就是节点(如果主矩阵中有M列,则图中有M个节点),它们由任意数量的边连接。图可以被认为是有向的或无向的,并且可以在边缘上有浮点值的权值。Loom甚至支持多图(允许节点对之间有多条边)。图存储为边和相关边权值的数组。

  • 行图和列图在使用ds.row_graphs 和 ds.col_graphs访问。例如:
ds.row_graphs.keys()      # Return list of row graphs
ds.col_graphs.KNN = ...   # Create or replace the column-oriented graph KNN
a = ds.col_graphs.KNN     # Assign the KNN column graph to variable a
del ds.col_graphs.KNN     # Delete the KNN graph

##Views

loompy Views的功能是通过切片将loom文件特定的内容读入到内存,然后进行查看。

ds.view[:, 10:20]

##Operations

###Map

  • 通过map方法可以在数据行或者列的维度上对数据进行迭代处理:
ds.map([np.mean, np.std], axis=1)

map()结合scan()可以遍历处理整个文件内容。

  • map对于函数设置的参数接受一个函数list,然后将每个函数都在整个数据进行遍历,就算一个函数也应该是list结构。
(means,) = ds.map([np.mean], axis=1)

###Permutation

  • 排列行或列的顺序:
rdering = np.random.permutation(np.arange(ds.shape[1]))
ds.permute(ordering, axis=1)

#排列文件中的行或列的顺序,是不需要将整个文件加载到RAM中。

###Scan

  • 对于非常大的织机文件,分批(batches)scan文件(沿着行或列)是非常有用的,以避免将整个文件加载到内存中。这可以使用scan()方法实现:
for (ix, selection, view) in ds.scan(axis=1):
  # do something with each view

#axis=0表示行,axis=1表示列;
#ix是提取内容的索引起始位置
#selection是提取的内容列的list
#view是一个loom对象;loom的一些方法都可以进行运用。

import numpy as np
import loompy
filename = "test.loom"
matrix = np.arange(10000).reshape(100,100)
row_attrs = { "SomeRowAttr": np.arange(100) }
col_attrs = { "SomeColAttr": np.arange(100) }
loompy.create(filename, matrix, row_attrs, col_attrs)


ds = loompy.connect("test.loom")
for (ix, selection, view) in ds.scan(axis=1):
    print(ix, selection)
    
0 [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
 96 97 98 99]
  • 还可以选定的列或行子集内容进行扫描。例如:
cells = # List of columns you want to see
for (ix, selection, view) in ds.scan(items=cells, axis=1):
  # do something with each view

#cell就是对应的index; array([ 0, 1, 2, 3])

loom R版本参考: loomR介绍及使用指南

#原文

API Walkthrough
Source code for loompy.loompy

相关文章

网友评论

    本文标题:loompy API

    本文链接:https://www.haomeiwen.com/subject/xriptltx.html