pnas-figure-guide · v1.0 · 2026-04-01 · sha256 0b0df0dfa2a4558f
pnas-figure-guide v1.0A
Immutable. This exact content never changes and is served at /api/v1/blob/0b0df0dfa2a4558f.
---
name: pnas-figure-guide
description: "Figure and image preparation guide for PNAS. Covers resolution (300-1000 PPI by type), file formats (TIFF, EPS, PDF), strict RGB-only color mode, Arial/Helvetica fonts, italicized uppercase panel labels, and automated image screening."
license: CC-BY-4.0
compatibility: Python 3.10+, Pillow, Matplotlib
metadata:
authors: HITS
version: "1.0"
---
# PNAS Figure Preparation Guide
## Overview
This guide provides the complete specifications for preparing figures for submission to **PNAS** (Proceedings of the National Academy of Sciences). PNAS is notable for its **strict RGB-only policy** (CMYK submissions are returned), **italicized uppercase panel labels**, and **automated image screening software**.
**Official reference**: https://www.pnas.org/author-center/submitting-your-manuscript
---
## Resolution Requirements
| Image Type | Minimum Resolution | Notes |
|---|---|---|
| Halftones (color/grayscale photos) | **300 PPI** | At publication size |
| Combination artwork (MS Office) | **600-900 DPI** | Mixed text and images |
| Line art (bitmap text/thin lines) | **1,000 PPI** | At publication size |
| LaTeX figures | — | High-quality PDF or EPS |
```python
from PIL import Image
def check_pnas_resolution(image_path, image_type='halftone'):
"""Check if image meets PNAS resolution requirements.
Args:
image_type: 'halftone' (300), 'combination' (600), or 'lineart' (1000)
"""
min_ppi = {'halftone': 300, 'combination': 600, 'lineart': 1000}
required = min_ppi.get(image_type, 300)
img = Image.open(image_path)
dpi = img.info.get('dpi', (72, 72))
print(f"Type: {image_type} | Required: {required} PPI | Actual: {dpi[0]} PPI")
if dpi[0] >= required:
print("PASS")
else:
print(f"FAIL: Need {required} PPI minimum")
return dpi[0] >= required
```
---
## File Format
| Format | Accepted |
|---|---|
| **TIFF** | Yes (preferred for raster) |
| **EPS** | Yes (fonts must be embedded) |
| **PDF** | Yes (fonts must be embedded) |
| **PPT** | Yes |
| **3D images** | PRC or U3D with 2D representation (TIFF/EPS/PDF) |
### Submission Stages
- **Initial submission**: Format-neutral — single PDF containing full manuscript, figures, and SI. High-resolution files not required.
- **Production phase**: Separate high-resolution figure uploads required.
---
## Figure Size and Dimensions
**IMPORTANT**: Provide images at **final publication size**, not full-page size.
| Layout | Width |
|---|---|
| 1 column | **8.7 cm** (3.43 in) |
| 1.5 columns | **11.4 cm** (4.5 in / 27 picas) |
| 2 columns | **17.8 cm** (7.0 in / 42.125 picas) |
| Maximum height | **22.5 cm** (9 in / 54 picas) |
```python
import matplotlib.pyplot as plt
PNAS_WIDTHS = {
'single': 8.7 / 2.54, # 3.43 inches
'middle': 11.4 / 2.54, # 4.49 inches
'double': 17.8 / 2.54, # 7.01 inches
}
PNAS_MAX_HEIGHT = 22.5 / 2.54 # 8.86 inches
def create_pnas_figure(layout='single', aspect_ratio=0.75):
"""Create a Matplotlib figure sized for PNAS."""
width = PNAS_WIDTHS[layout]
height = min(width * aspect_ratio, PNAS_MAX_HEIGHT)
fig, ax = plt.subplots(figsize=(width, height))
fig.set_dpi(300)
return fig, ax
```
---
## Color Mode
### CRITICAL: RGB Only
- **Submit in RGB color mode ONLY**
- **CMYK submissions will be returned for correction**
- Tag RGB images with originating ICC profile for accurate RGB-to-CMYK conversion
- PNAS manages print conversion using calibrated profiles
```python
from PIL import Image
def validate_pnas_color_mode(image_path):
"""PNAS strictly requires RGB. CMYK will be rejected."""
img = Image.open(image_path)
if img.mode == 'CMYK':
print("REJECTED: PNAS does not accept CMYK images")
print("Action: Convert to RGB before submission")
return False
elif img.mode in ('RGB', 'RGBA'):
print("PASS: Image is in RGB mode")
return True
else:
print(f"WARNING: Unexpected mode '{img.mode}'; convert to RGB")
return False
def convert_to_rgb(image_path, output_path):
"""Convert any image to RGB for PNAS submission."""
img = Image.open(image_path)
if img.mode != 'RGB':
img = img.convert('RGB')
print(f"Converted from {img.mode} to RGB")
img.save(output_path)
```
---
## Font Requirements
| Element | Specification |
|---|---|
| Approved fonts | **Arial, Helvetica, Times, Symbol, Mathematical Pi, European Pi** |
| Font size | **6-8 pt** at final publication size (minimum 2 mm when printed) |
| Consistency | Same font for all figures in manuscript |
| Text type | **Vector text** preferred (scales cleanly) |
| Embedding | **All fonts must be embedded** in EPS and PDF files |
### Panel Labels (PNAS-Specific Convention)
- **Italicized uppercase letters**: *A*, *B*, *C*, *D*, ...
- This is a distinctive PNAS convention — different from most other journals
```python
import matplotlib.pyplot as plt
def set_pnas_fonts():
"""Configure Matplotlib for PNAS figure fonts."""
plt.rcParams.update({
'font.family': 'sans-serif',
'font.sans-serif': ['Arial', 'Helvetica'],
'font.size': 7,
'axes.labelsize': 7,
'axes.titlesize': 7,
'xtick.labelsize': 6,
'ytick.labelsize': 6,
'legend.fontsize': 6,
})
def add_pnas_panel_labels(fig, axes):
"""Add PNAS-style italicized uppercase panel labels."""
import string
if not hasattr(axes, '__iter__'):
axes = [axes]
for i, ax in enumerate(axes):
label = string.ascii_uppercase[i]
ax.text(-0.1, 1.1, label,
transform=ax.transAxes,
fontsize=8,
fontstyle='italic',
fontweight='bold',
va='top',
ha='right',
fontfamily='Arial')
```
---
## Labeling Conventions
- Panel labels: **Italicized uppercase** (*A*, *B*, *C*)
- All text, numbers, letters, symbols: **6-12 pt (2-6 mm)** after reduction
- Text sizing must be **consistent within each graphic**
- Labels should match body text font conventions
---
## Image Integrity and Manipulation Policy
### PROHIBITED
- Enhancing, obscuring, moving, removing, or introducing any specific feature within an image
### PERMITTED
- Brightness, contrast, color balance adjustments applied to the **whole image** without obscuring or eliminating original information (including backgrounds)
### REQUIRED
- When combining images from multiple sources: make **explicit** by arrangement and figure legend text
- Name processing software in Methods section
- Indicate all manipulations in figure legends
- Original data must be available on request (missing data may result in rejection)
### Automated Screening
**PNAS uses screening software** to detect:
- Cloning and pasting artifacts
- Suspicious contrast adjustments that obscure data
- Inconsistent background pixelation
- Other signs of inappropriate image manipulation
### Accessibility
- Beginning with Volume 123, PNAS includes **alt text** for all journal figures to improve digital accessibility
---
## Python Quick Start: Full Validation
```python
from PIL import Image
import os
def validate_pnas_figure(image_path, image_type='halftone', layout='single'):
"""Full validation of a figure against PNAS requirements."""
img = Image.open(image_path)
issues = []
# 1. Resolution check
min_ppi = {'halftone': 300, 'combination': 600, 'lineart': 1000}
required = min_ppi.get(image_type, 300)
dpi = img.info.get('dpi', (72, 72))
if dpi[0] < required:
issues.append(f"Resolution {dpi[0]} PPI below {required} PPI for {image_type}")
# 2. STRICT RGB check
if img.mode == 'CMYK':
issues.append("REJECTED: CMYK not accepted. Must convert to RGB")
elif img.mode not in ('RGB', 'RGBA'):
issues.append(f"Color mode '{img.mode}' not standard; use RGB")
# 3. Dimension check at publication size
widths_cm = {'single': 8.7, 'middle': 11.4, 'double': 17.8}
max_height_cm = 22.5
if layout in widths_cm and dpi[0] > 0:
actual_w_cm = (img.size[0] / dpi[0]) * 2.54
actual_h_cm = (img.size[1] / dpi[1]) * 2.54
target_w = widths_cm[layout]
if actual_h_cm > max_height_cm:
issues.append(f"Height {actual_h_cm:.1f} cm exceeds max {max_height_cm} cm")
print(f"Print size: {actual_w_cm:.1f} x {actual_h_cm:.1f} cm (target width: {target_w} cm)")
# 4. Format check
fmt = img.format
accepted = ['TIFF', 'EPS', 'PDF', 'PNG', 'JPEG']
if fmt and fmt.upper() not in accepted:
issues.append(f"Format '{fmt}' not in preferred list (TIFF, EPS, PDF)")
# Report
print(f"=== PNAS Figure Validation ===")
print(f"Dimensions: {img.size[0]} x {img.size[1]} px")
print(f"DPI: {dpi[0]} x {dpi[1]}")
print(f"Color mode: {img.mode}")
if issues:
print(f"\nISSUES FOUND ({len(issues)}):")
for issue in issues:
print(f" - {issue}")
else:
print("\nAll checks PASSED")
return len(issues) == 0
```
---
## Pre-Submission Checklist
Before submitting figures to PNAS, verify:
- [ ] Halftones at 300+ PPI; line art at 1,000+ PPI
- [ ] File format is TIFF, EPS, or PDF
- [ ] **Color mode is RGB** (NOT CMYK — will be rejected)
- [ ] ICC profile tagged for accurate color conversion
- [ ] Figure width matches column layout (8.7 / 11.4 / 17.8 cm)
- [ ] Figure height does not exceed 22.5 cm
- [ ] Images provided at **final publication size**
- [ ] Font is Arial, Helvetica, or Times at 6-8 pt
- [ ] All fonts embedded in EPS/PDF
- [ ] Panel labels are **italicized uppercase** (*A*, *B*, *C*)
- [ ] Text sizing consistent within each figure
- [ ] All adjustments applied to entire image uniformly
- [ ] Multi-source composites explicitly indicated in legend
- [ ] Processing software named in Methods
- [ ] Original unprocessed data available for review
- [ ] Alt text prepared for accessibility
---
## References
- PNAS Submission Guidelines: https://www.pnas.org/author-center/submitting-your-manuscript
- PNAS Digital Art Guidelines: https://www.pnas.org/pb-assets/authors/digitalart.pdf
- PNAS Editorial Policies: https://www.pnas.org/author-center/editorial-and-journal-policies