Create publication-ready figures for Nature-style journal. Help me: 1) Design multi-panel figure showing experimental results, 2) Choose appropriate plot types (scatter, box, violin, heat map), 3) Apply consistent color scheme (colorblind-friendly), 4) Format axes, labels, legends professionally, 5) Ensure 300+ DPI resolution, 6) Write detailed figure caption, 7) Generate in Python (matplotlib/seaborn) or R (ggplot2)

Prompt
Create publication-ready figures for Nature-style journal. Help me: 1) Design multi-panel figure showing experimental results, 2) Choose appropriate plot types (scatter, box, violin, heat map), 3) Apply consistent color scheme (colorblind-friendly), 4) Format axes, labels, legends professionally, 5) Ensure 300+ DPI resolution, 6) Write detailed figure caption, 7) Generate in Python (matplotlib/seaborn) or R (ggplot2)
ChatGPTOpenAI
Create publication-ready figures for Nature-style journal. Help me: 1) Design multi-panel figure showing experimental results, 2) Choose appropriate plot types (scatter, box, violin, heat map), 3) Apply consistent color scheme (colorblind-friendly), 4) Format axes, labels, legends professionally, 5) Ensure 300+ DPI resolution, 6) Write detailed figure caption, 7) Generate in Python (matplotlib/seaborn) or R (ggplot2)

Creating publication-ready figures for a Nature-style journal involves attention to detail in both design and aesthetics. Below, I will outline how to create a multi-panel figure using Python with Matplotlib and Seaborn, focusing on the key requirements you've provided.

Step-by-Step Guide

1. Design Multi-Panel Figure


Suppose we have four experimental groups with different measurements (Group A, B, C, D) and we want to show:
  • A boxplot for the distribution of measurements.

  • A scatter plot to represent individual data points.

  • A heatmap to represent correlation between variables.

  • A violin plot to show the distribution along with median and quartiles.


2. Choose Appropriate Plot Types


  • Panel A: Boxplot of measurements (to show distribution).

  • Panel B: Scatter plot of individual measurements (to illustrate variability).

  • Panel C: Heatmap to visualize a correlation matrix.

  • Panel D: Violin plot for distribution with a focus on density.


3. Consistent Color Scheme


Use a colorblind-friendly palette, such as the 'Color Universal Design' (CUD) or 'Set1' from Matplotlib.

4. Format Axes, Labels, Legends


Ensure full labeling, readable font sizes, and legends where necessary.

5. Ensure 300+ DPI Resolution


Use dpi=300 when saving figures in Matplotlib.

6. Write Detailed Figure Caption


A detailed caption should explain each panel and what is being demonstrated.

Example Code in Python

Below is an illustrative example using randomly generated data.

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd

# Generate sample data
np.random.seed(42)
groups = ['A', 'B', 'C', 'D']
data = {group: np.random.normal(loc=i, scale=0.5, size=100) for i, group in enumerate(groups)}
df = pd.DataFrame(data)

# Create a correlation matrix for heatmap
corr = df.corr()

# Set up the figure and axes
fig, axs = plt.subplots(2, 2, figsize=(12, 10))
fig.suptitle('Experimental Results Overview', fontsize=16)

# Panel A: Boxplot
sns.boxplot(data=df, ax=axs[0, 0], palette='Set1')
axs[0, 0].set_title('Boxplot of Measurements', fontsize=14)
axs[0, 0].set_ylabel('Measurements', fontsize=12)

# Panel B: Scatter Plot
for group in groups:
axs[0, 1].scatter([group]*100, df[group], alpha=0.6, label=f'Group {group}')
axs[0, 1].set_title('Scatter Plot of Measurements', fontsize=14)
axs[0, 1].set_ylabel('Measurements', fontsize=12)
axs[0, 1].legend(title='Groups', fontsize=10)

# Panel C: Heatmap
sns.heatmap(corr, annot=True, ax=axs[1, 0], cmap='coolwarm', center=0, vmin=-1, vmax=1)
axs[1, 0].set_title('Correlation Matrix Heatmap', fontsize=14)

# Panel D: Violin Plot
sns.violinplot(data=df, ax=axs[1, 1], palette='Set1')
axs[1, 1].set_title('Violin Plot of Measurements', fontsize=14)
axs[1, 1].set_ylabel('Measurements', fontsize=12)

# Adjust layout
plt.tight_layout(rect=[0, 0.03, 1, 0.95])

# Save the figure
plt.savefig('experimental_results_figure.png', dpi=300)
plt.show()

7. Detailed Figure Caption


Figure 1. Experimental Results Overview.
(A) Boxplot showing the distribution of measurements among different experimental groups (A, B, C, D). (B) Scatter plot illustrating individual measurements per group, highlighting variability across samples. (C) Heatmap presenting the correlation matrix of the measured variables, indicating the strength and direction of correlations. (D) Violin plot representing the density and distribution of measurements per group, with the median and quartiles indicated.

Output


Once you run the above code, you will get a multi-panel figure saved as experimentalresultsfigure.png with a resolution of 300 DPI. This figure can then be directly used for a Nature-style journal submission.

{DateTime.UtcNow:HH:mm}
GeminiGoogle
Create publication-ready figures for Nature-style journal. Help me: 1) Design multi-panel figure showing experimental results, 2) Choose appropriate plot types (scatter, box, violin, heat map), 3) Apply consistent color scheme (colorblind-friendly), 4) Format axes, labels, legends professionally, 5) Ensure 300+ DPI resolution, 6) Write detailed figure caption, 7) Generate in Python (matplotlib/seaborn) or R (ggplot2)

This is a comprehensive request, and I'm happy to help you create a publication-ready, Nature-style multi-panel figure using Python (Matplotlib and Seaborn).

We'll design a figure showing experimental results from a hypothetical drug study, incorporating various plot types, a colorblind-friendly scheme, professional formatting, and a detailed caption.


Scenario for the Figure

Let's imagine a study investigating the effects of a novel compound (Drug X) on cellular processes. We have three conditions:

  • Vehicle: Control group.

  • Drug X (Low Dose): Treatment with a low concentration of Drug X.

  • Drug X (High Dose): Treatment with a high concentration of Drug X.


We measure the following:
  • Panel A: Cell viability (quantitative comparison across groups).

  • Panel B: Expression of a key target gene, "Gene A" (quantitative comparison).

  • Panel C: Correlation between "Gene A" expression and another related gene, "Gene B".

  • Panel D: Differential expression of several genes across the conditions (heatmap).



Design Principles for Nature-Style Figures


  • Clarity & Readability: Information should be easily digestible.

  • Conciseness: Avoid unnecessary clutter.

  • Consistency: Uniform font styles, sizes, line widths, and color schemes across panels.

  • Data Representation: Show individual data points where feasible, especially for smaller n.

  • Professional Aesthetics: Clean lines, appropriate whitespace, clear labels, and legends.

  • Colorblind-Friendly: Use perceptually distinct and safe color palettes.

  • High Resolution: Essential for print quality.



Python Code (Matplotlib & Seaborn)

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
from scipy import stats

# --- 1. Global Plot Settings ---
# Set general plot style for Nature-like aesthetics
sns.set_theme(
context="paper", # 'paper' for smaller elements, 'talk' for presentations
style="white", # No background grid by default
palette="colorblind", # Excellent colorblind-friendly palette
font_scale=1.2, # Scale font sizes (adjust for desired text size in final output)
rc={
"font.family": "sans-serif",
"font.sans-serif": ["Arial", "Helvetica", "DejaVu Sans"],
"axes.edgecolor": "#333333", # Darker grey for axis lines
"axes.labelcolor": "#333333",
"xtick.color": "#333333",
"ytick.color": "#333333",
"figure.dpi": 300, # Default DPI for figures
"savefig.dpi": 300 # Default DPI for saved figures
}
)

# Define custom colors for conditions using the 'colorblind' palette for consistency
palette_custom = sns.color_palette("colorblind", 3)
colors = {
'Vehicle': palette_custom[0], # Blue
'Drug X (Low)': palette_custom[1], # Orange
'Drug X (High)': palette_custom[2] # Green
}

# --- 2. Simulate Data ---
np.random.seed(42) # for reproducibility

# Group sizes (number of replicates per condition)
n_samples = 15

# Data for Panel A (Cell Viability)
data_a = {
'Condition': ['Vehicle'] * n_samples + ['Drug X (Low)'] * n_samples + ['Drug X (High)'] * n_samples,
'Cell Viability (%)': np.concatenate([
np.random.normal(100, 5, n_samples), # Vehicle
np.random.normal(115, 6, n_samples), # Drug X (Low) - slight increase
np.random.normal(130, 7, n_samples) # Drug X (High) - significant increase
])
}
df_a = pd.DataFrame(data_a)
df_a['Cell Viability (%)'] = np.clip(df_a['Cell Viability (%)'], 80, 150) # Clip to reasonable range

# Data for Panel B (Gene A Expression)
data_b = {
'Condition': ['Vehicle'] * n_samples + ['Drug X (Low)'] * n_samples + ['Drug X (High)'] * n_samples,
'Gene A Expression (Arbitrary Units)': np.concatenate([
np.random.normal(10, 1.5, n_samples), # Vehicle
np.random.normal(8, 1.2, n_samples), # Drug X (Low) - slight decrease
np.random.normal(5, 1.0, n_samples) # Drug X (High) - significant decrease
])
}
df_b = pd.DataFrame(data_b)
df_b['Gene A Expression (Arbitrary Units)'] = np.clip(df_b['Gene A Expression (Arbitrary Units)'], 2, 12)

# Data for Panel C (Gene A vs. Gene B Correlation)
# Gene B is positively correlated with Gene A, but Drug X decreases Gene A
gene_a_values_c = df_b['Gene A Expression (Arbitrary Units)'].values
gene_b_values_c = 1.5 * gene_a_values_c + np.random.normal(5, 2, len(gene_a_values_c))
df_c = pd.DataFrame({
'Gene A Expression (Arbitrary Units)': gene_a_values_c,
'Gene B Expression (Arbitrary Units)': gene_b_values_c,
'Condition': df_b['Condition'] # Keep conditions for potential coloring
})

# Data for Panel D (Heatmap of Differential Gene Expression)
gene_names = [f'Gene {i+1}' for i in range(15)]
conditions_heatmap = ['Vehicle', 'Drug X (Low)', 'Drug X (High)']
heatmap_data = pd.DataFrame(index=gene_names, columns=conditions_heatmap)

# Simulate different gene expression patterns
for i, gene in enumerate(gene_names):
if i < 5: # Genes downregulated by Drug X
heatmap_data.loc[gene, 'Vehicle'] = np.random.normal(10, 1)
heatmap_data.loc[gene, 'Drug X (Low)'] = np.random.normal(8, 1)
heatmap_data.loc[gene, 'Drug X (High)'] = np.random.normal(5, 0.8)
elif i < 10: # Genes upregulated by Drug X
heatmap_data.loc[gene, 'Vehicle'] = np.random.normal(5, 0.8)
heatmap_data.loc[gene, 'Drug X (Low)'] = np.random.normal(7, 1)
heatmap_data.loc[gene, 'Drug X (High)'] = np.random.normal(10, 1)
else: # Genes largely unchanged
heatmap_data.loc[gene, 'Vehicle'] = np.random.normal(7, 1)
heatmap_data.loc[gene, 'Drug X (Low)'] = np.random.normal(7.5, 1)
heatmap_data.loc[gene, 'Drug X (High)'] = np.random.normal(6.8, 0.9)

# Normalize heatmap data for visualization (e.g., Z-score scaling per gene)
heatmap_data_scaled = heatmap_data.apply(lambda x: (x - x.mean()) / x.std(), axis=1)

# --- 3. Create Multi-Panel Figure ---
fig, axes = plt.subplots(2, 2, figsize=(10, 9), constrained_layout=True) # 2 rows, 2 columns

# Adjust subplot spacing (optional, constrained_layout often handles well)
# plt.subplots_adjust(hspace=0.4, wspace=0.3)

# --- Panel A: Cell Viability (Violin Plot + Scatter) ---
ax = axes[0, 0]
sns.violinplot(
data=df_a,
x='Condition',
y='Cell Viability (%)',
ax=ax,
inner='quartile', # Show quartiles inside violins
linewidth=1,
cut=0, # Trim violins to the data range
palette=colors,
saturation=0.7 # Reduce saturation slightly
)
sns.stripplot(
data=df_a,
x='Condition',
y='Cell Viability (%)',
ax=ax,
jitter=0.2, # Add jitter to points to prevent overlap
color='black',
s=4, # Size of the individual points
alpha=0.6
)
ax.set_title('A', loc='left', fontweight='bold')
ax.set_xlabel('') # Remove x-label as conditions are self-explanatory
ax.set_ylabel('Cell Viability (%)')
ax.set_ylim(70, 140) # Consistent y-axis limits

# Add statistical annotations (manual for demonstration, use `statannotations` for complex cases)
# Example: Drug X (High) vs Vehicle
y_max = df_a['Cell Viability (%)'].max()
ax.text(0, y_max + 5, '***', ha='center', va='bottom', fontsize=12) # Vehicle
ax.text(2, y_max + 5, '***', ha='center', va='bottom', fontsize=12) # Drug X (High)
ax.plot([0, 0, 2, 2], [y_max + 2, y_max + 4, y_max + 4, y_max + 2], lw=1, c='k')
ax.text(1, y_max + 8, '***', ha='center', va='bottom', fontsize=12) # Bracket for 0-2
ax.plot([0, 0, 1, 1], [y_max-5, y_max-2, y_max-2, y_max-5], lw=1, c='k') # Vehicle vs Drug X (Low)
ax.text(0.5, y_max-1, '*', ha='center', va='bottom', fontsize=12) # Bracket for 0-1

# --- Panel B: Gene A Expression (Violin Plot + Scatter) ---
ax = axes[0, 1]
sns.violinplot(
data=df_b,
x='Condition',
y='Gene A Expression (Arbitrary Units)',
ax=ax,
inner='quartile',
linewidth=1,
cut=0,
palette=colors,
saturation=0.7
)
sns.stripplot(
data=df_b,
x='Condition',
y='Gene A Expression (Arbitrary Units)',
ax=ax,
jitter=0.2,
color='black',
s=4,
alpha=0.6
)
ax.set_title('B', loc='left', fontweight='bold')
ax.set_xlabel('')
ax.set_ylabel('Gene A Expression (AU)') # Use abbreviation
ax.set_ylim(2, 12)

# Add statistical annotations
y_min = df_b['Gene A Expression (Arbitrary Units)'].min()
ax.text(0, y_min - 2, '***', ha='center', va='top', fontsize=12) # Vehicle
ax.text(2, y_min - 2, '***', ha='center', va='top', fontsize=12) # Drug X (High)
ax.plot([0, 0, 2, 2], [y_min - 1, y_min - 1.5, y_min - 1.5, y_min - 1], lw=1, c='k')
ax.text(1, y_min - 2.5, '***', ha='center', va='top', fontsize=12)

# --- Panel C: Gene A vs. Gene B Correlation (Scatter Plot with Regression) ---
ax = axes[1, 0]
sns.scatterplot(
data=df_c,
x='Gene A Expression (Arbitrary Units)',
y='Gene B Expression (Arbitrary Units)',
hue='Condition', # Color points by condition
palette=colors,
s=50,
alpha=0.7,
ax=ax
)
# Add regression line for all data combined
slope, intercept, r_value, p_value, std_err = stats.linregress(
df_c['Gene A Expression (Arbitrary Units)'],
df_c['Gene B Expression (Arbitrary Units)']
)
sns.lineplot(
x=df_c['Gene A Expression (Arbitrary Units)'],
y=intercept + slope * df_c['Gene A Expression (Arbitrary Units)'],
color='grey',
linestyle='--',
ax=ax
)
ax.text(
0.05, 0.95,
f'R={r_value:.2f}\nP={p_value:.3f}',
transform=ax.transAxes,
fontsize=10,
verticalalignment='top',
bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="none", alpha=0.7)
)

ax.set_title('C', loc='left', fontweight='bold')
ax.set_xlabel('Gene A Expression (AU)')
ax.set_ylabel('Gene B Expression (AU)')
ax.legend(title='Condition', loc='upper left', bbox_to_anchor=(1, 1)) # Move legend outside
# Ensure legend does not overlap with text
ax.set_xlim(ax.get_xlim()[0], ax.get_xlim()[1] * 1.1) # Extend x-axis slightly if needed
ax.set_ylim(ax.get_ylim()[0], ax.get_ylim()[1] * 1.05) # Extend y-axis slightly if needed

# --- Panel D: Differential Gene Expression (Heatmap) ---
ax = axes[1, 1]
sns.heatmap(
heatmap_data_scaled,
cmap='RdBu_r', # Diverging colormap, red for high, blue for low
center=0, # Center the colormap at 0 (for scaled data)
linewidths=0.5, # Lines between cells
linecolor='white',
cbar_kws={'label': 'Scaled Expression (Z-score)'}, # Color bar label
yticklabels=True, # Show gene names
xticklabels=True, # Show condition names
ax=ax
)
ax.set_title('D', loc='left', fontweight='bold')
ax.set_xlabel('')
ax.tick_params(axis='y', rotation=0) # Ensure gene names are horizontal
ax.tick_params(axis='x', rotation=45, ha='right') # Rotate x-axis labels
ax.set_ylabel('Gene')

# --- 4. Final Touches & Save Figure ---
# Apply consistent formatting to all axes (remove top/right spines, inward ticks)
for ax in axes.flatten():
ax.spines[['right', 'top']].set_visible(False)
ax.tick_params(direction='in', length=4, width=1.5, colors='#333333') # Inward ticks

# Adjust layout to prevent overlaps
plt.tight_layout(rect=[0, 0, 0.98, 1]) # Adjust rect to make space for Panel C legend

# Save figure with high resolution
output_filename = 'nature_style_figure.png'
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
plt.show()
print(f"Figure saved as '{output_filename}' with 300 DPI.")


6. Detailed Figure Caption

Figure 1 | Effects of Drug X on cell viability and gene expression. A multi-panel figure illustrating the dose-dependent impact of Drug X on cellular parameters and gene regulation. a, Cell viability in response to Vehicle (control), Drug X (Low Dose), and Drug X (High Dose) treatments. Data are presented as violin plots, showing the distribution of individual data points (black circles) for each condition, with the inner box indicating the interquartile range (IQR) and the horizontal line representing the median. Whiskers extend to 1.5 times the IQR. Each circle represents an independent biological replicate (n=15 per group). Statistical significance was determined by one-way ANOVA followed by Tukey's HSD post-hoc test. ***P < 0.001, P < 0.05. b, Expression levels of the target gene, Gene A (arbitrary units, AU), across the Vehicle, Drug X (Low Dose), and Drug X (High Dose) conditions. Data representation is identical to panel a, with n=15 independent biological replicates per group. Statistical significance was determined by one-way ANOVA followed by Tukey's HSD post-hoc test. P < 0.001. c, Correlation between Gene A and Gene B expression levels (AU) across all experimental conditions. Each point represents an individual biological replicate (n=45 total), colored according to its treatment condition (Vehicle, blue; Drug X (Low), orange; Drug X (High), green). A dashed grey line indicates the linear regression fit for all data points. The Pearson correlation coefficient (R) and associated P-value are indicated. d**, Heatmap depicting the scaled expression (Z-score) of 15 selected genes across the three treatment conditions (Vehicle, Drug X (Low), Drug X (High)). Genes are listed on the y-axis, and conditions on the x-axis. Color intensity represents the relative expression level, with red indicating higher-than-average expression and blue indicating lower-than-average expression for each gene, centered around a Z-score of 0. Data were obtained from RNA sequencing experiments and normalized per gene. All data are representative of at least three independent experiments.


Explanation of Design Choices & Best Practices


  • Multi-Panel Design (2x2):

  • This layout is efficient for presenting related but distinct experimental findings.

  • plt.subplots(2, 2, ...) creates the grid.

  • constrained_layout=True helps automatically adjust spacing, preventing overlaps.

  • Plot Types:

  • Panels A & B (Cell Viability, Gene A Expression): Violin Plots + Stripplot:

  • Violin Plots: Excellent for showing the full distribution of data (density) and key statistics (median, quartiles via inner='quartile'). This is more informative than just a box plot, especially for non-normal distributions or smaller n.

  • Stripplot (with Jitter): Overlaid individual data points address the "show all data" guideline, which is crucial for Nature-style figures. Jitter (jitter=0.2) prevents points from overlapping entirely.

  • cut=0: Ensures the violins don't extend beyond the actual data range.

  • Panel C (Gene A vs. Gene B Correlation): Scatter Plot with Regression:

  • Scatter Plot: Standard for visualizing the relationship between two continuous variables.

  • hue='Condition': Colors points by condition, allowing visual assessment of whether the correlation holds true within or across groups.

  • sns.lineplot() for Regression: Clearly shows the trend. Including R-value and P-value strengthens the scientific message.

  • Panel D (Differential Gene Expression): Heatmap:

  • Heatmap: Ideal for visualizing patterns in high-dimensional data, like gene expression across multiple samples or conditions.

  • cmap='RdBur': A diverging colormap is perfect for scaled data (e.g., Z-scores or fold changes), where center=0 indicates no change, red indicates upregulation, and blue downregulation. r reverses the default RdBu order, making red generally signify 'high' and blue 'low'.

  • center=0: Important for diverging colormaps when data is normalized around a central value.

  • linewidths and linecolor: Improve cell delineation.

  • Consistent Color Scheme (Colorblind-Friendly):

  • sns.set_theme(palette="colorblind"): This is a robust choice for colorblind-friendly colors, ensuring accessibility.

  • palette_custom dictionary: Explicitly maps colors from the colorblind palette to your experimental conditions (Vehicle, Drug X (Low), Drug X (High)), ensuring consistency across all panels where these conditions appear.

  • RdBu_r for Heatmap: A well-established diverging colormap for expression data, which is also perceptually uniform and generally colorblind-friendly.

  • Professional Formatting:

  • sns.set_theme(...): Sets global font, style (white removes gridlines by default), and context (paper provides appropriate sizing for publications).

  • Font: font.family: "sans-serif" with a preference for "Arial" (or similar Helvetica/DejaVu Sans) is standard for scientific journals.

  • Axis Spines & Ticks: ax.spines[['right', 'top']].setvisible(False) removes distracting top and right borders. ax.tickparams(direction='in') makes ticks point inwards, which is common in Nature.

  • Labels & Titles: Clear, concise labels with units (%, AU). Panel labels (A, B, C, D) are bold and left-aligned.

  • Statistical Annotations: Manually added text (ax.text) and lines (ax.plot) for significance stars (***, *, etc.). For complex comparisons, dedicated libraries like statannotations are recommended.

  • Legends: Placed strategically (e.g., outside the plot for Panel C) to avoid overlapping data. title='Condition' is good practice.

  • plt.tight_layout(): Automatically adjusts subplot parameters for a tight layout, minimizing overlapping plot elements.

  • 300+ DPI Resolution:

  • plt.savefig('naturestylefigure.png', dpi=300, bboxinches='tight') explicitly sets the resolution to 300 DPI, which is generally the minimum for print-quality figures. bboxinches='tight' ensures no extra whitespace around the figure.

  • For vector graphics (preferred for publication), save as .svg or .pdf. For this example, .png is used to demonstrate the resolution.

  • Detailed Figure Caption:

  • Follows the structure requested: overall summary, then detailed description of each panel (A, B, C, D).

  • Includes definitions of data points, statistical tests (even if simulated here), significance levels, error bar interpretations (implied by violin plots), and sample sizes (n). This ensures the figure is self-contained and fully interpretable.


This setup provides a strong foundation for creating high-quality, publication-ready figures for Nature-style journals. Remember to replace simulated data with your actual experimental results.

{DateTime.UtcNow:HH:mm}
GrokxAI
Create publication-ready figures for Nature-style journal. Help me: 1) Design multi-panel figure showing experimental results, 2) Choose appropriate plot types (scatter, box, violin, heat map), 3) Apply consistent color scheme (colorblind-friendly), 4) Format axes, labels, legends professionally, 5) Ensure 300+ DPI resolution, 6) Write detailed figure caption, 7) Generate in Python (matplotlib/seaborn) or R (ggplot2)

I'll help you create a publication-ready, Nature-style multi-panel figure using Python with matplotlib and seaborn. Here's a comprehensive example that demonstrates best practices for scientific figures.

Complete Python Code for Nature-Style Figure

```python
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
from matplotlib import rcParams
from scipy import stats
import matplotlib.patches as mpatches

Set publication-ready style parameters


plt.style.use('default')
sns.set_style("white")
rcParams['font.family'] = 'Arial'
rcParams['font.size'] = 8
rcParams['axes.linewidth'] = 0.8
rcParams['xtick.major.width'] = 0.8
rcParams['ytick.major.width'] = 0.8
rcParams['axes.labelsize'] = 9
rcParams['xtick.labelsize'] = 8
rcParams['ytick.labelsize'] = 8
rcParams['legend.fontsize'] = 8
rcParams['figure.dpi'] = 300

Colorblind-friendly ColorBrewer palette (Nature-recommended)


COLORS = {
'blue': '#0072B2',
'orange': '#D55E00',
'green': '#009E73',
'red': '#CC79A7',
'sky': '#56B4E9',
'yellow': '#F0E442',
'grey': '#999999'
}

Generate sample biological data (gene expression with conditions)


np.random.seed(42)
n_samples = 50

Panel A: Scatter plot with regression line


data_a = {
'WT': np.concatenate([np.random.normal(5, 1, nsamples), np.random.normal(5.5, 1.2, nsamples)]),
'Mut': np.concatenate([np.random.normal(4, 0.8, nsamples), np.random.normal(4.5, 1, nsamples)]),
'Ctrl': np.concatenate([np.random.normal(3, 0.9, nsamples), np.random.normal(3.2, 1.1, nsamples)])
}
xa = np.concatenate([np.random.normal(100, 20, nsamples*3),
np.random.normal(150, 25, n_samples*3)])

df_a = pd.DataFrame({
'Expression': np.concatenate(list(data_a.values())),
'Time': np.tile(np.repeat([1, 2], n_samples), 3),
'Condition': np.tile(np.repeat(['WT', 'Mut', 'Ctrl'], n_samples), 2),
'X': x_a
})

Panel B: Box and violin plots


data_b = {
'WT': np.random.lognormal(1.5, 0.5, n_samples*2),
'Mut': np.random.lognormal(1.2, 0.6, n_samples*2),
'KO': np.random.lognormal(1.8, 0.4, n_samples*2)
}
df_b = pd.DataFrame({
'Expression': np.concatenate([datab['WT'], datab['Mut'], data_b['KO']]),
'Condition': np.repeat(['WT', 'Mut', 'KO'], n_samples*2)
})

Panel C: Heatmap


genes = ['Gene1', 'Gene2', 'Gene3', 'Gene4', 'Gene5', 'Gene6']
samples = ['S1', 'S2', 'S3', 'S4', 'S5', 'S6']
data_matrix = np.random.random((6, 6)) * 4
dfc = pd.DataFrame(datamatrix, index=genes, columns=samples)

Panel D: Correlation heatmap


conditions = ['WT', 'Mut', 'KO', 'Ctrl']
corr_matrix = pd.DataFrame(
np.array([[1.0, 0.85, 0.65, 0.45],
[0.85, 1.0, 0.75, 0.55],
[0.65, 0.75, 1.0, 0.85],
[0.45, 0.55, 0.85, 1.0]]),
index=conditions, columns=conditions
)

Create the multi-panel figure


fig = plt.figure(figsize=(8.5, 6.5), dpi=300) # Nature typical size
gs = fig.addgridspec(3, 4, heightratios=[1, 1, 1],
width_ratios=[1, 1, 1, 1],
hspace=0.4, wspace=0.3,
left=0.05, right=0.95,
bottom=0.08, top=0.95)

Panel A: Scatter plot with regression


ax1 = fig.add_subplot(gs[0, :2])
sns.scatterplot(data=df_a, x='X', y='Expression',
hue='Condition', style='Time',
palette={k: COLORS[k] for k in ['blue', 'orange', 'green']},
s=40, alpha=0.7, ax=ax1)

Add regression lines for each condition


for condition in df_a['Condition'].unique():
subset = dfa[dfa['Condition'] == condition]
z = np.polyfit(subset['X'], subset['Expression'], 1)
p = np.poly1d(z)
ax1.plot(subset['X'], p(subset['X']),
color=COLORS[list(COLORS.keys())[list(COLORS.keys()).index(condition)]],
linestyle='-', linewidth=1.5, alpha=0.8)

ax1.set_xlabel('Protein Concentration (ΞM)', fontsize=9)
ax1.set_ylabel('Gene Expression (log2)', fontsize=9)
ax1.set_title('a', loc='left', weight='bold', fontsize=12, pad=10)
ax1.legend(bboxtoanchor=(1.05, 1), loc='upper left', frameon=False)
ax1.grid(True, alpha=0.3, linestyle='-', linewidth=0.5)

Panel B: Violin + Box plot overlay


ax2 = fig.add_subplot(gs[0, 2:])
palette_b = {k: COLORS[k] for k in ['blue', 'red', 'green']}
bp = sns.boxplot(data=df_b, x='Condition', y='Expression',
palette=palette_b, width=0.6, ax=ax2,
boxprops=dict(linewidth=1.2, alpha=0.7),
medianprops=dict(color='white', linewidth=1.5))
vp = sns.violinplot(data=df_b, x='Condition', y='Expression',
palette=palette_b, ax=ax2, alpha=0.3,
inner=None, linewidth=0.5)

ax2.set_xlabel('Genotype', fontsize=9)
ax2.set_ylabel('Expression Level', fontsize=9)
ax2.set_title('b', loc='left', weight='bold', fontsize=12, pad=10)
ax2.grid(True, alpha=0.3, linestyle='-', linewidth=0.5, axis='y')

Add statistical annotations (example p-values)


ymax = ax2.getylim()[1]
for i, cond in enumerate(['WT', 'Mut', 'KO']):
if i < len(['WT', 'Mut', 'KO']) - 1:
ax2.plot([i, i+1], [ymax0.95, ymax0.95],
color='black', linewidth=1)
ax2.text((i + i + 1)/2, y_max*0.97, 'n.s.',
ha='center', fontsize=8, color='black')

Panel C: Heatmap


ax3 = fig.add_subplot(gs[1, :2])
sns.heatmap(df_c, annot=True, fmt='.1f', cmap='viridis',
cbar_kws={'label': 'Expression Level', 'shrink': 0.8},
ax=ax3, linewidths=0.5, linecolor='white')

ax3.set_xlabel('Samples', fontsize=9)
ax3.set_ylabel('Genes', fontsize=9)
ax3.set_title('c', loc='left', weight='bold', fontsize=12, pad=10)

Panel D: Correlation heatmap


ax4 = fig.add_subplot(gs[1, 2:])
sns.heatmap(corrmatrix, annot=True, fmt='.2f', cmap='RdBur',
center=0, square=True,
cbar_kws={'label': 'Correlation', 'shrink': 0.8},
ax=ax4, linewidths=0.5, linecolor='white')

ax4.set_xlabel('Conditions', fontsize=9)
ax4.set_ylabel('Conditions', fontsize=9)
ax4.set_title('d', loc='left', weight='bold', fontsize=12, pad=10)

Panel E: Bar plot with error bars


ax5 = fig.add_subplot(gs[2, :2])
conditions_e = ['WT', 'Mut', 'KO']
means = [2.5, 2.1, 2.8]
sems = [0.1, 0.12, 0.08]

bars = ax5.bar(conditions_e, means, yerr=sems, capsize=5,
color=[COLORS['blue'], COLORS['orange'], COLORS['green']],
alpha=0.8, edgecolor='black', linewidth=0.8

{DateTime.UtcNow:HH:mm}

Analysis

This comparison demonstrates the different approaches each AI model takes when responding to the same prompt. Here are the key differences observed:

Response Characteristics

ChatGPT: Provides a direct response with 60 sentences.

Gemini: Provides a direct response with 292 sentences.

Grok: Provides a concise response with 173 sentences.

Key Takeaways

  • Each model brings unique strengths to this type of query
  • Response styles vary significantly between models
  • Consider your specific use case when choosing between these models

Try This Comparison Yourself

Want to test these models with your own prompts? Visit SNEOS.com to compare AI responses side-by-side in real-time.


This comparison was generated using the SNEOS AI Comparison ToolPublished: October 15, 2025 | Models: ChatGPT, Gemini, Grok