Answers.Body: <p>After a lot of experimentation with the various parameters I was able to get a heatmap that is rather close to the one generated by Seurat!</p>
  <pre><code># Unique is used to eliminate duplicated genes,
  # this is done automatically by Seurat DoHeatmap
  features &lt;- unique(most_significant_other_cells_markers$gene)
  
  # Extract the expression data for the selected genes from the scaled layer
  expr_matrix &lt;- as.matrix(
    GetAssayData(
      breast_cancer_patients_other_cells, 
      layer = &quot;scale.data&quot;, 
      assay = &quot;SCT&quot;
    )[
      features,
    ]
  )
  
  # Prepare cell type annotations
  cell_types &lt;- Idents(breast_cancer_patients_other_cells)
  # Create vector with unique and sorted cell types
  unique_cell_types &lt;- sort(unique(cell_types))
  
  # Create color palette for cell types
  cell_type_colors &lt;- setNames(
    gg_color_hue(length(unique_cell_types)),
    unique_cell_types
  )
  
  # Recreate the Seurat expression scale
  palette_expression_level = circlize::colorRamp2(
    c(min(expr_matrix), median(expr_matrix), min(2.5, max(expr_matrix))),
    c(&quot;#FF00FF&quot;, &quot;#000000&quot;, &quot;#FFFF00&quot;))
  
  # Create the heatmap with ComplexHeatmap
  ht = Heatmap(
    matrix = expr_matrix,
    row_order = features,
    name = &quot;expression&quot;,
    column_split = factor(cell_types, levels = unique_cell_types),
    # Do not cluster rows or columns otherwise row_order/column_order are ignored
    cluster_rows = FALSE,
    cluster_columns = FALSE,
    column_title_rot = 0,
    show_column_names = FALSE,
    show_column_dend = FALSE,
    show_row_names = TRUE,
    show_row_dend = FALSE,
    cluster_column_slices = TRUE,
    column_gap = unit(0.5, &quot;mm&quot;),
    row_names_gp = gpar(fontsize = 5),
    # The column title can be either a title for all the columns
    # or a vector with a name for every column
    column_title = unique_cell_types,
    column_title_gp = gpar(fontsize = 7),
    # Add the annotation bars on top
    top_annotation = HeatmapAnnotation(
      # Give a name to the annotation, not used on the actual plot
      name = &quot;Clusters&quot;,
      # Annotate the columns
      which = &quot;column&quot;,
      # First annotation - clusters
      cluster = cell_types,
      # Second annotation - patients
      patient = breast_cancer_patients_other_cells@meta.data$Patient.ID,
      # Color palettes
      col = list(cluster = cell_type_colors, patient = palette_patients),
      show_legend = c(FALSE, TRUE),
      gap = unit(1, &quot;mm&quot;),
      simple_anno_size = unit(2, &quot;mm&quot;),
      annotation_name_gp = gpar(fontsize = 6)
    ),
    # Color scale for expression
    col = palette_expression_level,
    # Otherwise you get random vertical white lines where there should not be any
    use_raster = FALSE
  )
  # Put the legends on the right in a single column
  draw(ht, merge_legend = TRUE)
  </code></pre>
  <p><a href="https://i.sstatic.net/KB0eUrGy.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/KB0eUrGy.png" alt="Heatmap generated with the R package ComplexHeatmap" /></a></p>
  <p>Thank you!</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-12-16T17:52:27.423Z
Answers.Text: Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer).
Answers.UserDisplayName: Community
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-12-17T05:22:44.187Z
Answers.Text: Thanks for this; are you able to explain what you did, or provide some of the code that generated this image?
Answers.UserDisplayName: gringer
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-12-18T01:36:37.407Z
Answers.Text: I added the code now, it has a few comments which I think should be sufficient to clarify what I did. Let me know if you think something needs an explanation :)
Answers.UserDisplayName: Alberto Fabbri
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-12-18T02:07:11.843Z
Answers.Text: Fabulous @AlbertoFabbri huge thanks. I do recommend the OP is upvoted for reporting back to the site. Much appreciated.
Answers.UserDisplayName: M__
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-12-16T16:57:41.737Z
Answers.LastActivityDate: 2024-12-18T01:33:40.903Z
Answers.LastEditDate: 2024-12-18T01:33:40.903Z
Answers.UserDisplayName: Alberto Fabbri
Answers.Body: <p>Regarding the data range, you should be able to take the scaled data directly from the Seurat object, without having to do any additional scaling:</p>
  <pre><code> expr_matrix &lt;- as.matrix(
    GetAssayData(
      slot = &quot;scale.data&quot;, # &lt;--
      breast_cancer_patients_other_cells, 
      layer = &quot;data&quot;, 
      assay = &quot;SCT&quot;)[
      most_significant_other_cells_markers$gene, 
      ]
    )
  </code></pre>
  <p>FWIW, you can look at the <code>DoHeatmap</code> code by typing the function name without brackets into the R console. This may help in understanding how data points are coloured and scaled:</p>
  <pre><code>&gt; DoHeatmap
  function (object, features = NULL, cells = NULL, group.by = &quot;ident&quot;, 
      group.bar = TRUE, group.colors = NULL, disp.min = -2.5, disp.max = NULL, 
      slot = &quot;scale.data&quot;, assay = NULL, label = TRUE, size = 5.5, 
      hjust = 0, vjust = 0, angle = 45, raster = TRUE, draw.lines = TRUE, 
      lines.width = NULL, group.bar.height = 0.02, combine = TRUE) 
  {
      assay &lt;- assay %||% DefaultAssay(object = object)
      DefaultAssay(object = object) &lt;- assay
      cells &lt;- cells %||% colnames(x = object[[assay]])
  ...
          }
          plot &lt;- plot + theme(line = element_blank())
          plots[[i]] &lt;- plot
      }
      if (combine) {
          plots &lt;- wrap_plots(plots)
      }
      return(plots)
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-12-12T07:22:09.280Z
Answers.LastActivityDate: 2024-12-12T07:31:13.430Z
Answers.LastEditDate: 2024-12-12T07:31:13.430Z
Answers.UserDisplayName: gringer
Answers.Body: <p>HHMmmmm I'll give this a shot as I'm brushing up my R and I do need to  answer questions once in a while. Note, there are stronger R codes on this site than I.
  Try the following code:</p>
  <pre><code># Extract the expression data for the selected genes
  valid_genes &lt;- intersect(rownames(GetAssayData(breast_cancer_patients_other_cells, assay = &quot;SCT&quot;)), 
                           most_significant_other_cells_markers$gene)
  expr_matrix &lt;- as.matrix(
    GetAssayData(
      breast_cancer_patients_other_cells, 
      layer = &quot;scale.data&quot;, 
      assay = &quot;SCT&quot;)[valid_genes, ]
  )
  
  # Scale the rows
  zero_var_rows &lt;- apply(expr_matrix, 1, var) == 0
  expr_matrix_scaled &lt;- expr_matrix
  expr_matrix_scaled[!zero_var_rows, ] &lt;- t(scale(t(expr_matrix[!zero_var_rows, ])))
  expr_matrix_scaled[zero_var_rows, ] &lt;- 0
  
  # Prepare cell type annotations
  cell_types &lt;- if (is.null(Idents(breast_cancer_patients_other_cells))) {
    breast_cancer_patients_other_cells@meta.data$cell_type_column
  } else {
    Idents(breast_cancer_patients_other_cells)
  }
  
  # Create color palette for cell types
  unique_cell_types &lt;- unique(cell_types)
  cell_type_colors &lt;- setNames(rainbow(length(unique_cell_types)), unique_cell_types)
  
  # Define palette for expression level
  valid_values &lt;- expr_matrix_scaled[!is.na(expr_matrix_scaled) &amp; !is.infinite(expr_matrix_scaled)]
  palette_expression_level &lt;- colorRamp2(
    c(min(valid_values), median(valid_values), max(valid_values)),
    c(&quot;#FF00FF&quot;, &quot;#000000&quot;, &quot;#FFFF00&quot;)
  )
  
  # Define palette for patients
  palette_patients &lt;- setNames(rainbow(length(unique(breast_cancer_patients_other_cells@meta.data<span class="math-container">$Patient.ID))),
                           unique(breast_cancer_patients_other_cells@meta.data$</span>Patient.ID))
  
  # Save png
  png(here(&quot;test.png&quot;), width = 15, height = 20, units = &quot;cm&quot;, res = 1000)
  
  # Create the heatmap with ComplexHeatmap
  Heatmap(
    expr_matrix_scaled,
    name = &quot;Expression&quot;,
    column_split = factor(cell_types),
    cluster_rows = TRUE,
    cluster_columns = TRUE,
    column_title_rot = 0,
    show_column_names = FALSE,
    show_column_dend = FALSE,
    show_row_names = TRUE,
    show_row_dend = FALSE,
    cluster_column_slices = TRUE,
    column_gap = unit(0.5, &quot;mm&quot;),
    row_names_gp = gpar(fontsize = 5),
    column_title = &quot;Top 10 Differentially Expressed Genes per Cluster&quot;,
    top_annotation = HeatmapAnnotation(
      Cluster = cell_types,
      Patient = breast_cancer_patients_other_cells@meta.data$Patient.ID,
      col = list(Cluster = cell_type_colors, Patient = palette_patients),
      show_legend = TRUE,
      gap = unit(1, &quot;mm&quot;),
      simple_anno_size = unit(2, &quot;mm&quot;),
      annotation_name_gp = gpar(fontsize = 6)
    ),
    col = palette_expression_level
  )
  
  # Save image
  dev.off()
  </code></pre>
  <p>Potential issues:</p>
  <ul>
  <li>Does <code>layer = &quot;data&quot;</code> argument in GetAssayData exist or is it incorrect for the assay SCT? By default, Seurat uses layers like &quot;counts&quot;, &quot;data&quot;, or &quot;scale.data&quot;.</li>
  <li><code>most_significant_other_cells_markers$gene</code> might contain genes not present in the dataset?</li>
  <li>The <code>scale()</code> function may encounter rows with constant values (zero variance), that gives NaN values after scaling.</li>
  <li><code>Idents</code> might not have been set correctly for the Seurat object. If Idents returns NULL, this step will fail.</li>
  </ul>
  <p>Plus lots more</p>
  <hr />
  <p>What I do recommend is debugging:</p>
  <pre><code>print(dim(expr_matrix_scaled))
  print(head(cell_types))
  print(unique(cell_types))
  </code></pre>
  <p>This is what an R-coding expert would almost certainly request unless they've encountered exactly the same situation.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-12-11T15:57:17.257Z
Answers.Text: Your code works but it gives a Heatmap quite similar to the one I posted here. The SCT assay has all three layers, the count layer should contain adjusted counts. All the markers should be in the expression matrix as the find markers function has been run on the same assay. Idents is set properly as it is also needed to generate the heatmap with the Seurat function DoHeatmap. I did not know about the problem with the variance, interesting!
Answers.UserDisplayName: Alberto Fabbri
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-12-11T20:54:51.680Z
Answers.Text: Okay thanks. Well I tried a collection of stuff - but I'm no expert. 
  If this was Python I could nail it.
Answers.UserDisplayName: M__
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-12-11T15:25:11.563Z
Answers.LastActivityDate: 2024-12-11T15:51:59.337Z
Answers.LastEditDate: 2024-12-11T15:51:59.337Z
Answers.UserDisplayName: M__
Body: <p>I generated a heatmap using the <code>DoHeatmap</code> function in the Seurat package. The heatmap looks fine but I want to add a second annotation bar on top with the patient data. <a href="https://github.com/satijalab/seurat/issues/2201" rel="nofollow noreferrer">According to this Seurat GitHub issue</a> it is not possible therefore, I decided to recreate an identical heatmap from scratch using ComplexHeatmap. This has proven more challenging than I thought and I would like some help.</p>
  <h3>Find markers</h3>
  <pre><code># Find all markers of the other clusters
  other_cells_markers_data &lt;- FindAllMarkers(
    breast_cancer_patients_other_cells,
    test.use = &quot;wilcox&quot;,
    assay = &quot;SCT&quot;,
    only.pos = FALSE,
    random.seed = 5)
  
  most_significant_other_cells_markers &lt;- other_cells_markers_data %&gt;%
    group_by(cluster) %&gt;%
    dplyr::filter(avg_log2FC &gt; 1 &amp; p_val_adj &lt; 0.05) %&gt;%
    slice_head(n = 10) %&gt;%
    ungroup()
  </code></pre>
  <h3>Seurat Heatmap</h3>
  <pre><code>DoHeatmap(
      breast_cancer_patients_other_cells,
      features = most_significant_other_cells_markers$gene,
      assay = &quot;SCT&quot;,
      label = TRUE,
      size = 2
     ) + theme(
       axis.text.y = element_text(size = 5),
     ) + labs(
       title = paste(&quot;Other cells clusters&quot;),
       subtitle = &quot;Top 10 Differentially Expressed Genes per Cluster&quot;
     )
  </code></pre>
  <p><a href="https://i.sstatic.net/kDvjxKb8.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/kDvjxKb8.png" alt="enter image description here" /></a></p>
  <h3>ComplexHeatmap</h3>
  <pre><code># Extract the expression data for the selected genes
  expr_matrix &lt;- as.matrix(
    GetAssayData(
      breast_cancer_patients_other_cells, 
      layer = &quot;data&quot;, 
      assay = &quot;SCT&quot;)[
      most_significant_other_cells_markers$gene, 
      ]
    )
  ## scale the rows
  expr_matrix_scaled&lt;- t(scale(t(expr_matrix)))
  
  # Prepare cell type annotations
  cell_types &lt;- Idents(breast_cancer_patients_other_cells)
  
  # Create color palette for cell types
  unique_cell_types &lt;- unique(cell_types)
  cell_type_colors &lt;- setNames(
    rainbow(length(unique_cell_types)),
    unique_cell_types
  )
  
  # Recreate the Seurat expression scale
  palette_expression_level = colorRamp2(
    c(min(expr_matrix_scaled), median(expr_matrix_scaled), max(expr_matrix_scaled)),
    c(&quot;#FF00FF&quot;, &quot;#000000&quot;, &quot;#FFFF00&quot;))
  
  # Save png
  png(here(&quot;test.png&quot;),width=15,height=20,units=&quot;cm&quot;,res=1000)
  
  # Create the heatmap with ComplexHeatmap
  Heatmap(
    matrix = expr_matrix_scaled,
    name = &quot;Expression&quot;,
    column_split = factor(cell_types),
    cluster_rows = TRUE,
    cluster_columns = TRUE,
    column_title_rot = 0,
    show_column_names = FALSE,
    show_column_dend = FALSE,
    show_row_names = TRUE,
    show_row_dend = FALSE,
    cluster_column_slices = TRUE,
    column_gap = unit(0.5, &quot;mm&quot;),
    row_names_gp = gpar(fontsize = 5),
    column_title = &quot;Top 10 Differentially Expressed Genes per Cluster&quot;,
    top_annotation = HeatmapAnnotation(
      Cluster = cell_types,
      Patient = breast_cancer_patients_other_cells@meta.data$Patient.ID,
      col = list(Cluster = cell_type_colors, Patient = palette_patients),
      show_legend = TRUE,
      gap = unit(1, &quot;mm&quot;),
      simple_anno_size = unit(2, &quot;mm&quot;),
      annotation_name_gp = gpar(fontsize = 6)
    ),
    # Color scale for expression
    col = palette_expression_level
  )
  
  # Save image
  dev.off()
  </code></pre>
  <p><a href="https://i.sstatic.net/f5uNCVD6.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/f5uNCVD6.png" alt="enter image description here" /></a></p>
  <p>What parameters am I missing?</p>
  <h2>EDIT: Debugging info</h2>
  <pre class="lang-r prettyprint-override"><code>&gt; print(dim(expr_matrix_scaled))
  [1]    92 30702
  &gt; print(head(cell_types))
   5_171 27_171 28_171 29_171 31_171 34_171 
       7      7      7      7      7      7 
  Levels: 0 1 2 3 4 5 6 7 8 9
  &gt; print(unique(cell_types))
   [1] 7 0 2 9 8 1 4 5 3 6
  Levels: 0 1 2 3 4 5 6 7 8 9
  </code></pre>
  
Tags: <r><seurat><complexheatmap>
Title: Reproduce Seurat Heatmap with ComplexHeatmap
ThreadText: # Reproduce Seurat Heatmap with ComplexHeatmap
  
  (Asked by: username_0 on 2024-12-11)
  
  I generated a heatmap using the `DoHeatmap` function in the Seurat package. The heatmap looks fine but I want to add a second annotation bar on top with the patient data. [According to this Seurat GitHub issue](https://github.com/satijalab/seurat/issues/2201) it is not possible therefore, I decided to recreate an identical heatmap from scratch using ComplexHeatmap. This has proven more challenging than I thought and I would like some help.
  
  ### Find markers
  
  ```
  # Find all markers of the other clusters
  other_cells_markers_data <- FindAllMarkers(
    breast_cancer_patients_other_cells,
    test.use = "wilcox",
    assay = "SCT",
    only.pos = FALSE,
    random.seed = 5)
  
  most_significant_other_cells_markers <- other_cells_markers_data %>%
    group_by(cluster) %>%
    dplyr::filter(avg_log2FC > 1 & p_val_adj < 0.05) %>%
    slice_head(n = 10) %>%
    ungroup()
  
  ```
  
  ### Seurat Heatmap
  
  ```
  DoHeatmap(
      breast_cancer_patients_other_cells,
      features = most_significant_other_cells_markers$gene,
      assay = "SCT",
      label = TRUE,
      size = 2
     ) + theme(
       axis.text.y = element_text(size = 5),
     ) + labs(
       title = paste("Other cells clusters"),
       subtitle = "Top 10 Differentially Expressed Genes per Cluster"
     )
  
  ```
  
  [![enter image description here](https://i.sstatic.net/kDvjxKb8.png)](https://i.sstatic.net/kDvjxKb8.png)
  
  ### ComplexHeatmap
  
  ```
  # Extract the expression data for the selected genes
  expr_matrix <- as.matrix(
    GetAssayData(
      breast_cancer_patients_other_cells, 
      layer = "data", 
      assay = "SCT")[
      most_significant_other_cells_markers$gene, 
      ]
    )
  ## scale the rows
  expr_matrix_scaled<- t(scale(t(expr_matrix)))
  
  # Prepare cell type annotations
  cell_types <- Idents(breast_cancer_patients_other_cells)
  
  # Create color palette for cell types
  unique_cell_types <- unique(cell_types)
  cell_type_colors <- setNames(
    rainbow(length(unique_cell_types)),
    unique_cell_types
  )
  
  # Recreate the Seurat expression scale
  palette_expression_level = colorRamp2(
    c(min(expr_matrix_scaled), median(expr_matrix_scaled), max(expr_matrix_scaled)),
    c("#FF00FF", "#000000", "#FFFF00"))
  
  # Save png
  png(here("test.png"),width=15,height=20,units="cm",res=1000)
  
  # Create the heatmap with ComplexHeatmap
  Heatmap(
    matrix = expr_matrix_scaled,
    name = "Expression",
    column_split = factor(cell_types),
    cluster_rows = TRUE,
    cluster_columns = TRUE,
    column_title_rot = 0,
    show_column_names = FALSE,
    show_column_dend = FALSE,
    show_row_names = TRUE,
    show_row_dend = FALSE,
    cluster_column_slices = TRUE,
    column_gap = unit(0.5, "mm"),
    row_names_gp = gpar(fontsize = 5),
    column_title = "Top 10 Differentially Expressed Genes per Cluster",
    top_annotation = HeatmapAnnotation(
      Cluster = cell_types,
      Patient = breast_cancer_patients_other_cells@meta.data$Patient.ID,
      col = list(Cluster = cell_type_colors, Patient = palette_patients),
      show_legend = TRUE,
      gap = unit(1, "mm"),
      simple_anno_size = unit(2, "mm"),
      annotation_name_gp = gpar(fontsize = 6)
    ),
    # Color scale for expression
    col = palette_expression_level
  )
  
  # Save image
  dev.off()
  
  ```
  
  [![enter image description here](https://i.sstatic.net/f5uNCVD6.png)](https://i.sstatic.net/f5uNCVD6.png)
  
  What parameters am I missing?
  
  ## EDIT: Debugging info
  
  ```r
  > print(dim(expr_matrix_scaled))
  [1]    92 30702
  > print(head(cell_types))
   5_171 27_171 28_171 29_171 31_171 34_171 
       7      7      7      7      7      7 
  Levels: 0 1 2 3 4 5 6 7 8 9
  > print(unique(cell_types))
   [1] 7 0 2 9 8 1 4 5 3 6
  Levels: 0 1 2 3 4 5 6 7 8 9
  
  ```
  
  **Tags:** r, seurat, complexheatmap
  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_0 on 2024-12-16. Score: 1 | Accepted answer
  
  After a lot of experimentation with the various parameters I was able to get a heatmap that is rather close to the one generated by Seurat!
  
  ```
  # Unique is used to eliminate duplicated genes,
  # this is done automatically by Seurat DoHeatmap
  features <- unique(most_significant_other_cells_markers$gene)
  
  # Extract the expression data for the selected genes from the scaled layer
  expr_matrix <- as.matrix(
    GetAssayData(
      breast_cancer_patients_other_cells, 
      layer = "scale.data", 
      assay = "SCT"
    )[
      features,
    ]
  )
  
  # Prepare cell type annotations
  cell_types <- Idents(breast_cancer_patients_other_cells)
  # Create vector with unique and sorted cell types
  unique_cell_types <- sort(unique(cell_types))
  
  # Create color palette for cell types
  cell_type_colors <- setNames(
    gg_color_hue(length(unique_cell_types)),
    unique_cell_types
  )
  
  # Recreate the Seurat expression scale
  palette_expression_level = circlize::colorRamp2(
    c(min(expr_matrix), median(expr_matrix), min(2.5, max(expr_matrix))),
    c("#FF00FF", "#000000", "#FFFF00"))
  
  # Create the heatmap with ComplexHeatmap
  ht = Heatmap(
    matrix = expr_matrix,
    row_order = features,
    name = "expression",
    column_split = factor(cell_types, levels = unique_cell_types),
    # Do not cluster rows or columns otherwise row_order/column_order are ignored
    cluster_rows = FALSE,
    cluster_columns = FALSE,
    column_title_rot = 0,
    show_column_names = FALSE,
    show_column_dend = FALSE,
    show_row_names = TRUE,
    show_row_dend = FALSE,
    cluster_column_slices = TRUE,
    column_gap = unit(0.5, "mm"),
    row_names_gp = gpar(fontsize = 5),
    # The column title can be either a title for all the columns
    # or a vector with a name for every column
    column_title = unique_cell_types,
    column_title_gp = gpar(fontsize = 7),
    # Add the annotation bars on top
    top_annotation = HeatmapAnnotation(
      # Give a name to the annotation, not used on the actual plot
      name = "Clusters",
      # Annotate the columns
      which = "column",
      # First annotation - clusters
      cluster = cell_types,
      # Second annotation - patients
      patient = breast_cancer_patients_other_cells@meta.data$Patient.ID,
      # Color palettes
      col = list(cluster = cell_type_colors, patient = palette_patients),
      show_legend = c(FALSE, TRUE),
      gap = unit(1, "mm"),
      simple_anno_size = unit(2, "mm"),
      annotation_name_gp = gpar(fontsize = 6)
    ),
    # Color scale for expression
    col = palette_expression_level,
    # Otherwise you get random vertical white lines where there should not be any
    use_raster = FALSE
  )
  # Put the legends on the right in a single column
  draw(ht, merge_legend = TRUE)
  
  ```
  
  [![Heatmap generated with the R package ComplexHeatmap](https://i.sstatic.net/KB0eUrGy.png)](https://i.sstatic.net/KB0eUrGy.png)
  
  Thank you!
  
  > **Comments:**
  > **username_1**: Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer).  
  > **username_2**: Thanks for this; are you able to explain what you did, or provide some of the code that generated this image?  
  > **username_0**: I added the code now, it has a few comments which I think should be sufficient to clarify what I did. Let me know if you think something needs an explanation :)  
  > **username_3**: Fabulous @username_0 huge thanks. I do recommend the OP is upvoted for reporting back to the site. Much appreciated.  
  
  ---
  
  ### Answer by username_2 on 2024-12-12. Score: 1
  
  Regarding the data range, you should be able to take the scaled data directly from the Seurat object, without having to do any additional scaling:
  
  ```
   expr_matrix <- as.matrix(
    GetAssayData(
      slot = "scale.data", # <--
      breast_cancer_patients_other_cells, 
      layer = "data", 
      assay = "SCT")[
      most_significant_other_cells_markers$gene, 
      ]
    )
  
  ```
  
  FWIW, you can look at the `DoHeatmap` code by typing the function name without brackets into the R console. This may help in understanding how data points are coloured and scaled:
  
  ```
  > DoHeatmap
  function (object, features = NULL, cells = NULL, group.by = "ident", 
      group.bar = TRUE, group.colors = NULL, disp.min = -2.5, disp.max = NULL, 
      slot = "scale.data", assay = NULL, label = TRUE, size = 5.5, 
      hjust = 0, vjust = 0, angle = 45, raster = TRUE, draw.lines = TRUE, 
      lines.width = NULL, group.bar.height = 0.02, combine = TRUE) 
  {
      assay <- assay %||% DefaultAssay(object = object)
      DefaultAssay(object = object) <- assay
      cells <- cells %||% colnames(x = object[[assay]])
  ...
          }
          plot <- plot + theme(line = element_blank())
          plots[[i]] <- plot
      }
      if (combine) {
          plots <- wrap_plots(plots)
      }
      return(plots)
  }
  
  ```
  
  
  ---
  
  ### Answer by username_3 on 2024-12-11. Score: 0
  
  HHMmmmm I'll give this a shot as I'm brushing up my R and I do need to answer questions once in a while. Note, there are stronger R codes on this site than I.
  Try the following code:
  
  ```
  # Extract the expression data for the selected genes
  valid_genes <- intersect(rownames(GetAssayData(breast_cancer_patients_other_cells, assay = "SCT")), 
                           most_significant_other_cells_markers$gene)
  expr_matrix <- as.matrix(
    GetAssayData(
      breast_cancer_patients_other_cells, 
      layer = "scale.data", 
      assay = "SCT")[valid_genes, ]
  )
  
  # Scale the rows
  zero_var_rows <- apply(expr_matrix, 1, var) == 0
  expr_matrix_scaled <- expr_matrix
  expr_matrix_scaled[!zero_var_rows, ] <- t(scale(t(expr_matrix[!zero_var_rows, ])))
  expr_matrix_scaled[zero_var_rows, ] <- 0
  
  # Prepare cell type annotations
  cell_types <- if (is.null(Idents(breast_cancer_patients_other_cells))) {
    breast_cancer_patients_other_cells@meta.data$cell_type_column
  } else {
    Idents(breast_cancer_patients_other_cells)
  }
  
  # Create color palette for cell types
  unique_cell_types <- unique(cell_types)
  cell_type_colors <- setNames(rainbow(length(unique_cell_types)), unique_cell_types)
  
  # Define palette for expression level
  valid_values <- expr_matrix_scaled[!is.na(expr_matrix_scaled) & !is.infinite(expr_matrix_scaled)]
  palette_expression_level <- colorRamp2(
    c(min(valid_values), median(valid_values), max(valid_values)),
    c("#FF00FF", "#000000", "#FFFF00")
  )
  
  # Define palette for patients
  palette_patients <- setNames(rainbow(length(unique(breast_cancer_patients_other_cells@meta.data$Patient.ID))),
                           unique(breast_cancer_patients_other_cells@meta.data$Patient.ID))
  
  # Save png
  png(here("test.png"), width = 15, height = 20, units = "cm", res = 1000)
  
  # Create the heatmap with ComplexHeatmap
  Heatmap(
    expr_matrix_scaled,
    name = "Expression",
    column_split = factor(cell_types),
    cluster_rows = TRUE,
    cluster_columns = TRUE,
    column_title_rot = 0,
    show_column_names = FALSE,
    show_column_dend = FALSE,
    show_row_names = TRUE,
    show_row_dend = FALSE,
    cluster_column_slices = TRUE,
    column_gap = unit(0.5, "mm"),
    row_names_gp = gpar(fontsize = 5),
    column_title = "Top 10 Differentially Expressed Genes per Cluster",
    top_annotation = HeatmapAnnotation(
      Cluster = cell_types,
      Patient = breast_cancer_patients_other_cells@meta.data$Patient.ID,
      col = list(Cluster = cell_type_colors, Patient = palette_patients),
      show_legend = TRUE,
      gap = unit(1, "mm"),
      simple_anno_size = unit(2, "mm"),
      annotation_name_gp = gpar(fontsize = 6)
    ),
    col = palette_expression_level
  )
  
  # Save image
  dev.off()
  
  ```
  
  Potential issues:
  
  * Does `layer = "data"` argument in GetAssayData exist or is it incorrect for the assay SCT? By default, Seurat uses layers like "counts", "data", or "scale.data".
  * `most_significant_other_cells_markers$gene` might contain genes not present in the dataset?
  * The `scale()` function may encounter rows with constant values (zero variance), that gives NaN values after scaling.
  * `Idents` might not have been set correctly for the Seurat object. If Idents returns NULL, this step will fail.
  
  Plus lots more
  
  ---
  
  What I do recommend is debugging:
  
  ```
  print(dim(expr_matrix_scaled))
  print(head(cell_types))
  print(unique(cell_types))
  
  ```
  
  This is what an R-coding expert would almost certainly request unless they've encountered exactly the same situation.
  
  > **Comments:**
  > **username_0**: Your code works but it gives a Heatmap quite similar to the one I posted here. The SCT assay has all three layers, the count layer should contain adjusted counts. All the markers should be in the expression matrix as the find markers function has been run on the same assay. Idents is set properly as it is also needed to generate the heatmap with the Seurat function DoHeatmap. I did not know about the problem with the variance, interesting!  
  > **username_3**: Okay thanks. Well I tried a collection of stuff - but I'm no expert.  If this was Python I could nail it.  
  
  ---
  
  