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