<p>Based on your approaches, I recommend running HashSoLo before performing extensive QC filtering. The reason is that HashSoLo's classification works best when it can analyze the complete distribution of HTO signals across all cells - removing cells early through QC might skew this distribution and affect the accuracy of cell classification. In your first approach, you were on the right track by running HashSoLo early in the workflow, but I suggest a slight modification: start with reading in your 10x data, make the variable names unique, and store the raw counts. Then apply minimal gene filtering (just the min_counts=1) before running HashSoLo on the HTO data. After getting the HashSoLo classifications, transfer these results back to your main object and proceed with your standard QC steps including filtering for minimum genes per cell, genes present in minimum cells, and mitochondrial content analysis. Do this process separately for each sample while keeping track of sample identity, then concatenate them. This way, you maintain the integrity of the HTO classification while ensuring proper quality control of your gene expression data. After concatenation, you can consider addressing batch effects if they're present in your data. This order ensures you don't inadvertently remove informative cells before hashtag classification while still maintaining rigorous quality control for your final analysis.</p>

CC BY-SA 4.0
2024-11-25T01:44:28.093Z
2024-11-25T01:44:28.093Z
Yi-Fen Cheng
<p>I am trying to use hashsolo and I want to make sure that I have done things correctly.</p>
<p>I did the below:</p>
<pre><code>#import files
A= sc.read_10x_h5('filtered_feature_bc_matrix.h5', gex_only=False)
A.var_names_make_unique()
A.layers[&quot;counts&quot;] = A.X.copy()
sc.pp.filter_genes(A, min_counts=1)

#hashsolo
hto=A[:,A.var_names.str.startswith('HTO')].copy()
hashsolo.hashsolo(hto)
hashsolo.plot_qc_checks_cell_hashing(cell_hashing_data) #nothing gets plotted
A.obs['most_likely_hypothesis'] = hto.obs['most_likely_hypothesis']
A.obs['Classification'] = hto.obs['Classification']
</code></pre>
<p>Then since I have two samples for which I did hashsolo (A and B) I concatenated the objects and continued with the scanpy analysis like shown below:</p>
<pre><code>sc.pl.highest_expr_genes(A_B, n_top=20, )
sc.pp.filter_cells(A_B, min_genes=200)
sc.pp.filter_genes(A_B, min_cells=3)
print(A_B.n_obs, A_B.n_vars)
</code></pre>
<p>and I continued with the mitochondria QC and the rest of the analysis.</p>
<p>Is that correct?</p>
<p>I am wondering if I should have done it differently. Like shown below</p>
<pre><code>A= sc.read_10x_h5('filtered_feature_bc_matrix.h5', gex_only=False)
A.var_names_make_unique() Then the 
sc.pl.highest_expr_genes(A, n_top=20, )
sc.pp.filter_cells(A, min_genes=200)
sc.pp.filter_genes(A, min_cells=3)
print(A.n_obs, A.n_vars)
</code></pre>
<p>and following the QC (filtering and mitochondria) and make the hto list and use hashsolo and then concatenate the 2 samples (A and B).</p>

<rna-seq><python><hashing>
How to use hashsolo for demultiplexing hashtags?
# How to use hashsolo for demultiplexing hashtags?

(Asked by: username_0 on 2023-04-26)

I am trying to use hashsolo and I want to make sure that I have done things correctly.
I did the below:
#import files
A= sc.read_10x_h5('filtered_feature_bc_matrix.h5', gex_only=False)
A.var_names_make_unique()
A.layers["counts"] = A.X.copy()
sc.pp.filter_genes(A, min_counts=1)

#hashsolo
hto=A[:,A.var_names.str.startswith('HTO')].copy()
hashsolo.hashsolo(hto)
hashsolo.plot_qc_checks_cell_hashing(cell_hashing_data) #nothing gets plotted
A.obs['most_likely_hypothesis'] = hto.obs['most_likely_hypothesis']
A.obs['Classification'] = hto.obs['Classification']

Then since I have two samples for which I did hashsolo (A and B) I concatenated the objects and continued with the scanpy analysis like shown below:
sc.pl.highest_expr_genes(A_B, n_top=20, )
sc.pp.filter_cells(A_B, min_genes=200)
sc.pp.filter_genes(A_B, min_cells=3)
print(A_B.n_obs, A_B.n_vars)

and I continued with the mitochondria QC and the rest of the analysis.
Is that correct?
I am wondering if I should have done it differently. Like shown below
A= sc.read_10x_h5('filtered_feature_bc_matrix.h5', gex_only=False)
A.var_names_make_unique() Then the 
sc.pl.highest_expr_genes(A, n_top=20, )
sc.pp.filter_cells(A, min_genes=200)
sc.pp.filter_genes(A, min_cells=3)
print(A.n_obs, A.n_vars)

and following the QC (filtering and mitochondria) and make the hto list and use hashsolo and then concatenate the 2 samples (A and B).

**Tags:** rna-seq, python, hashing

---

## 1 answers

### Answer by username_1 on 2024-11-25. Score: 1

Based on your approaches, I recommend running HashSoLo before performing extensive QC filtering. The reason is that HashSoLo's classification works best when it can analyze the complete distribution of HTO signals across all cells - removing cells early through QC might skew this distribution and affect the accuracy of cell classification. In your first approach, you were on the right track by running HashSoLo early in the workflow, but I suggest a slight modification: start with reading in your 10x data, make the variable names unique, and store the raw counts. Then apply minimal gene filtering (just the min\_counts=1) before running HashSoLo on the HTO data. After getting the HashSoLo classifications, transfer these results back to your main object and proceed with your standard QC steps including filtering for minimum genes per cell, genes present in minimum cells, and mitochondrial content analysis. Do this process separately for each sample while keeping track of sample identity, then concatenate them. This way, you maintain the integrity of the HTO classification while ensuring proper quality control of your gene expression data. After concatenation, you can consider addressing batch effects if they're present in your data. This order ensures you don't inadvertently remove informative cells before hashtag classification while still maintaining rigorous quality control for your final analysis.


---

