or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/pypi-adjusttext

Iteratively adjust text position in matplotlib plots to minimize overlaps

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/adjusttext@1.3.x

To install, run

npx @tessl/cli install tessl/pypi-adjusttext@1.3.0

0

# adjustText

1

2

A Python library for iteratively adjusting text position in matplotlib plots to minimize overlaps between text annotations and data points. Inspired by the ggrepel R package, adjustText implements an intelligent algorithm that automatically repositions matplotlib text labels to improve plot readability without manual intervention.

3

4

## Package Information

5

6

- **Package Name**: adjustText

7

- **Language**: Python

8

- **Installation**: `pip install adjustText`

9

- **Dependencies**: numpy, matplotlib, scipy

10

11

## Core Imports

12

13

```python

14

from adjustText import adjust_text

15

```

16

17

Import with version:

18

19

```python

20

from adjustText import adjust_text, __version__

21

```

22

23

Import utility functions:

24

25

```python

26

from adjustText import overlap_intervals

27

```

28

29

Alternative import:

30

31

```python

32

import adjustText

33

# Access: adjustText.adjust_text()

34

```

35

36

## Basic Usage

37

38

```python

39

import matplotlib.pyplot as plt

40

import numpy as np

41

from adjustText import adjust_text

42

43

# Create sample data

44

x = np.random.randn(20)

45

y = np.random.randn(20)

46

47

# Create scatter plot

48

fig, ax = plt.subplots()

49

ax.scatter(x, y)

50

51

# Create text labels

52

texts = []

53

for i, (xi, yi) in enumerate(zip(x, y)):

54

texts.append(ax.text(xi, yi, f'Point {i}', fontsize=9))

55

56

# Automatically adjust text positions to avoid overlaps

57

adjust_text(texts, ax=ax)

58

59

plt.show()

60

```

61

62

Advanced usage with additional objects to avoid:

63

64

```python

65

import matplotlib.pyplot as plt

66

import numpy as np

67

from adjustText import adjust_text

68

69

# Create data and plot

70

x = np.random.randn(15)

71

y = np.random.randn(15)

72

73

fig, ax = plt.subplots(figsize=(10, 8))

74

scatter = ax.scatter(x, y, s=100, c='red', alpha=0.7)

75

76

# Add some additional objects to avoid

77

objects = [scatter]

78

79

# Create text labels

80

texts = []

81

for i, (xi, yi) in enumerate(zip(x, y)):

82

texts.append(ax.text(xi, yi, f'Label {i}', fontsize=10))

83

84

# Adjust text positions avoiding both other texts and scatter points

85

adjust_text(texts,

86

objects=objects,

87

expand=(1.1, 1.3),

88

force_text=(0.05, 0.25),

89

force_static=(0.02, 0.25),

90

ax=ax)

91

92

plt.show()

93

```

94

95

## Capabilities

96

97

### Text Position Adjustment

98

99

Automatically adjusts the positions of matplotlib text objects to minimize overlaps using an iterative physics-based algorithm.

100

101

```python { .api }

102

def adjust_text(

103

texts,

104

x=None,

105

y=None,

106

objects=None,

107

target_x=None,

108

target_y=None,

109

avoid_self=True,

110

prevent_crossings=True,

111

force_text=(0.1, 0.2),

112

force_static=(0.1, 0.2),

113

force_pull=(0.01, 0.01),

114

force_explode=(0.1, 0.5),

115

pull_threshold=10,

116

expand=(1.05, 1.2),

117

max_move=(10, 10),

118

explode_radius="auto",

119

ensure_inside_axes=True,

120

expand_axes=False,

121

only_move={"text": "xy", "static": "xy", "explode": "xy", "pull": "xy"},

122

ax=None,

123

min_arrow_len=5,

124

time_lim=None,

125

iter_lim=None,

126

*args,

127

**kwargs

128

):

129

"""

130

Iteratively adjusts the locations of texts to minimize overlaps.

131

132

Must be called after all plotting is complete, as the function needs

133

the final axes dimensions to work correctly.

134

135

Parameters:

136

- texts: List of matplotlib.text.Text objects to adjust

137

- x, y: Array-like coordinates of points to repel from (optional, with avoid_self=True original text positions are added)

138

- objects: List of matplotlib objects to avoid or PathCollection/list of Bbox objects (must have get_window_extent() method)

139

- target_x, target_y: Array-like coordinates to connect adjusted texts to (optional, defaults to original text positions)

140

- avoid_self: Whether to repel texts from their original positions (bool, default True)

141

- prevent_crossings: Whether to prevent arrows from crossing each other (bool, default True, experimental)

142

- force_text: Multiplier for text-text repulsion forces (tuple[float, float] | float, default (0.1, 0.2))

143

- force_static: Multiplier for text-object repulsion forces (tuple[float, float] | float, default (0.1, 0.2))

144

- force_pull: Multiplier for pull-back-to-origin forces (tuple[float, float] | float, default (0.01, 0.01))

145

- force_explode: Multiplier for initial explosion forces (tuple[float, float] | float, default (0.1, 0.5))

146

- pull_threshold: Distance threshold for pull-back forces in display units (float, default 10)

147

- expand: Multipliers for expanding text bounding boxes (tuple[float, float], default (1.05, 1.2))

148

- max_move: Maximum movement per iteration in display units (tuple[int, int] | int | None, default (10, 10))

149

- explode_radius: Initial explosion radius in display units or "auto" (str | float, default "auto")

150

- ensure_inside_axes: Whether to keep texts inside axes boundaries (bool, default True)

151

- expand_axes: Whether to expand axes to fit all texts (bool, default False)

152

- only_move: Movement restrictions per force type (dict, default {"text": "xy", "static": "xy", "explode": "xy", "pull": "xy"})

153

- ax: Matplotlib axes object (matplotlib.axes.Axes | None, uses plt.gca() if None)

154

- min_arrow_len: Minimum arrow length to draw in display units (float, default 5)

155

- time_lim: Maximum time for adjustment in seconds (float | None, default None)

156

- iter_lim: Maximum number of iterations (int | None, default None)

157

- args, kwargs: Additional arguments passed to FancyArrowPatch for arrow styling

158

159

Returns:

160

- texts: List of adjusted text objects (list)

161

- patches: List of arrow patches connecting texts to targets (list of FancyArrowPatch or Annotation objects)

162

"""

163

```

164

165

### Package Version

166

167

Access the package version:

168

169

```python { .api }

170

__version__: str

171

# Package version string (e.g., "1.3.0")

172

```

173

174

### Utility Functions

175

176

The package exports utility functions for advanced use cases:

177

178

```python { .api }

179

def overlap_intervals(starts1, ends1, starts2, ends2, closed=False, sort=False):

180

"""

181

Find overlapping intervals between two sets of intervals.

182

183

Parameters:

184

- starts1, ends1: First set of interval coordinates (numpy.ndarray)

185

- starts2, ends2: Second set of interval coordinates (numpy.ndarray)

186

- closed: Whether to treat intervals as closed (bool)

187

- sort: Whether to sort results (bool)

188

189

Returns:

190

- overlap_ids: Array of overlapping interval pair indices (numpy.ndarray)

191

"""

192

```

193

194

```python { .api }

195

def arange_multi(starts, stops=None, lengths=None):

196

"""

197

Create concatenated ranges of integers for multiple start/length pairs.

198

199

Parameters:

200

- starts: Start values for each range (numpy.ndarray)

201

- stops: Stop values for each range (numpy.ndarray, optional)

202

- lengths: Length values for each range (numpy.ndarray, optional)

203

204

Returns:

205

- concat_ranges: Concatenated ranges (numpy.ndarray)

206

207

Notes:

208

Either stops or lengths must be provided, but not both.

209

"""

210

```

211

212

### Additional Importable Functions

213

214

The following functions are technically importable from the main module but are primarily intended for internal use:

215

216

```python { .api }

217

def get_renderer(fig):

218

"""

219

Get a renderer for the given figure.

220

221

Parameters:

222

- fig: Matplotlib figure object

223

224

Returns:

225

- renderer: Figure renderer object

226

227

Raises:

228

- ValueError: If unable to determine renderer

229

"""

230

```

231

232

```python { .api }

233

def intersect(seg1, seg2):

234

"""

235

Check if two line segments intersect.

236

237

Parameters:

238

- seg1: First line segment as (x1, y1, x2, y2) tuple

239

- seg2: Second line segment as (x3, y3, x4, y4) tuple

240

241

Returns:

242

- intersects: Whether segments intersect (bool)

243

"""

244

```

245

246

```python { .api }

247

def get_bboxes(objs, r=None, expand=(1, 1), ax=None):

248

"""

249

Get bounding boxes for matplotlib objects.

250

251

Parameters:

252

- objs: List of objects or PathCollection to get bboxes from

253

- r: Renderer (optional, deduced from ax if None)

254

- expand: Expansion factors for bboxes (x, y) (tuple, default (1, 1))

255

- ax: Axes object (optional, uses current axes if None)

256

257

Returns:

258

- bboxes: List of bounding box objects

259

"""

260

```

261

262

**Note**: These functions are not part of the stable public API and may change in future versions. They are documented here for completeness as they are technically accessible via import.

263

264

## Types

265

266

```python { .api }

267

# Force specification types

268

ForceValue = tuple[float, float] | float

269

270

# Movement restriction values

271

MovementRestriction = str # "x", "y", "xy", "x+", "x-", "y+", "y-"

272

273

# Only move dictionary type

274

OnlyMoveDict = dict[str, MovementRestriction] # Keys: "text", "static", "explode", "pull"

275

```

276

277

## Algorithm Overview

278

279

The adjustText algorithm works in several phases:

280

281

1. **Explosion Phase**: Initially separates overlapping texts using KDTree proximity detection

282

2. **Iterative Adjustment**: Applies multiple forces simultaneously:

283

- **Repulsion forces**: Push texts away from each other and static objects

284

- **Pull forces**: Gently pull texts back toward original positions

285

- **Boundary forces**: Keep texts within axes if `ensure_inside_axes=True`

286

3. **Arrow Generation**: Creates connecting arrows between final text positions and target points

287

288

The algorithm is highly configurable through force multipliers, movement restrictions, and termination conditions, making it suitable for both simple automatic adjustment and fine-tuned control for complex visualizations.

289

290

## Common Use Cases

291

292

- **Scientific publications**: Automatically position labels on scatter plots and data visualizations

293

- **Data exploration**: Quickly make plots readable without manual text positioning

294

- **Automated reporting**: Generate clear visualizations in data processing pipelines

295

- **Complex multi-series plots**: Handle overlapping labels across multiple data series

296

297

The library is designed to be called as the final step in plot creation, after all other plotting operations are complete, ensuring optimal text positioning based on the final plot layout.