Comments (10)
Thank you for reporting and glad you like the package!
Could you please provide an example with this behaviour? I can't reproduce it with a couple examples I tried, the results with and without saving steps are the same.
from adjusttext.
Here is a stripped down version of my plotting code which should show the problem described above.
Without save_steps=True or adding ax.draw(r) to the adjust_text routine, the labels end up going over the border of the map.
import pickle
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits import basemap
from collections import namedtuple, OrderedDict
from adjustText import adjust_text
def polygon(x, y, r, n):
angle= (2 * np.pi) / n
#convert r to degrees
r = r * 1.852 # conveting to nautical miles
r = r / (111.12)
px_list = []
py_list = []
for i in range(0, n):
px = r / np.cos(y * 0.0174532925) * np.sin(angle * i) + x
py = r * np.cos(angle * i) + y
px_list.append(px)
py_list.append(py)
px_list.append(px_list[0])
py_list.append(py_list[0])
return px_list, py_list
def create_basemap(lat_array, lon_array):
lon_2d, lat_2d = np.meshgrid(lon_array, lat_array)
cen_lat = np.sum(lat_array) / len(lat_array)
cen_lon = np.sum(lon_array) / len(lon_array)
proj = 'merc'
m = basemap.Basemap(projection=proj,
llcrnrlon=lon_2d[0, 0],
llcrnrlat=lat_2d[0, 0],
urcrnrlon=lon_2d[-1, -1],
urcrnrlat=lat_2d[-1, -1],
lat_0=cen_lat,
lon_0=cen_lon,
resolution='h')
x , y = m(lon_2d[:, :],lat_2d[:, :])
return m, x ,y
Point = namedtuple('Point', ['lat', 'lon'])
example_points = [Point(lat=-20.0, lon=110.7),
Point(lat=-20.2, lon=110.8),
Point(lat=-20.5, lon=110.9),
Point(lat=-20.3, lon=111.2),
Point(lat=-20.0, lon=111.1),
Point(lat=-19.8, lon=111.0),
Point(lat=-19.8, lon=110.8),
Point(lat=-19.9, lon=110.6),
Point(lat=-20.2, lon=110.4),
Point(lat=-20.6, lon=110.3),
Point(lat=-21.2, lon=109.9),
Point(lat=-21.9, lon=109.4),
Point(lat=-22.8, lon=108.8),
Point(lat=-23.9, lon=108.3),
Point(lat=-25.0, lon=107.8),
Point(lat=-26.1, lon=107.8),
Point(lat=-27.3, lon=107.7),
Point(lat=-28.5, lon=108.8),
Point(lat=-29.2, lon=109.6),
Point(lat=-29.8, lon=110.7),
Point(lat=-30.0, lon=112.0)
]
lat_array = np.arange(-40, -9.8, 0.1)
lon_array = np.arange(97.7, 122.0, 0.1)
m, x, y = create_basemap(lat_array, lon_array)
# below is a basic figure with no adjust, looks horrible
fig = plt.figure()
ax = fig.add_subplot(111)
for indx, pt in enumerate(example_points):
x_pt, y_pt = m(pt.lon, pt.lat)
m.scatter(x_pt, y_pt, s=20, c='k')
if np.mod(indx, 2) == 0:
my_text = plt.text(x_pt, y_pt, 'str about this long',
ha='right', va='center', fontsize=10,
fontweight='bold', color='k')
plt.savefig('basic_figure.png')
# below is a very stripped down version of my plot, there are more things plotted near
# the points, but I have removed them for the example purposes.
# the aim is to not have the labels too close to the points, but also not have them go over
# the border of the map
fig = plt.figure()
ax = fig.add_subplot(111)
label_list = []
repel_obj = []
for indx, pt in enumerate(example_points):
x_pt, y_pt = m(pt.lon, pt.lat)
m.scatter(x_pt, y_pt, s=20, c='k')
if np.mod(indx, 2) == 0:
my_text = plt.text(x_pt,
y_pt,
'str this long',
ha='right',
va='center',
fontsize=10,
fontweight='bold',
color='k')
label_list.append(my_text)
# create an area around the points that the labels should not enter
# this is done by creating a fake circle around each point, with alpha=0 so we
# do not see it, normally the plot has additional items plotted near the points
circle_x, circle_y = polygon(pt.lon, pt.lat, 70, 32)
map_circle_x, map_circle_y = m(circle_x, circle_y)
repel_circle = plt.fill(map_circle_x, map_circle_y, color='m', alpha=0.0)
repel_obj += repel_circle
# without save_steps or adding ax.draw(r) to adjust_text routine the labels go
# over the border.
adjust_text(label_list,
add_objects=repel_obj,
ax=ax,
force_points=0.5,
force_objects=0.5,
lim=100,
arrowprops=dict(arrowstyle="->", connectionstyle='arc3', color='k',lw=1.0)#,
#save_steps=True
)
plt.savefig('adjust_figure.png')
from adjusttext.
Any chance you can make an example without using basemap?.. I don't have it installed, and it doesn't seem to be as easy as I hoped it would be to install it.
Also, just in case, I have to mention that objects always work as rectangles, even if you create a circle, since the library uses their binding boxes to calculate overlaps...
from adjusttext.
(Also, to remove labels further away from points you can specify higher expand_points
values)
from adjusttext.
Sorry I should have thought of that basemap could cause an issue, and it is not even really required for this example. Attached is the code with basemap removed (images attached before look the same so I won't upload them again)
At one stage I played with the expand_points value but didn't get the results I was looking for. However, I probably didn't give it a good enough go so I will look into that further.
For now, here is the code that shows the save_steps issue.
import pickle
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from collections import namedtuple, OrderedDict
from adjustText import adjust_text
def polygon(x, y, r, n):
angle= (2 * np.pi) / n
#convert r to degrees
r = r * 1.852 # conveting to nautical miles
r = r / (111.12)
px_list = []
py_list = []
for i in range(0, n):
px = r / np.cos(y * 0.0174532925) * np.sin(angle * i) + x
py = r * np.cos(angle * i) + y
px_list.append(px)
py_list.append(py)
px_list.append(px_list[0])
py_list.append(py_list[0])
return px_list, py_list
Point = namedtuple('Point', ['lat', 'lon'])
example_points = [Point(lat=-20.0, lon=110.7),
Point(lat=-20.2, lon=110.8),
Point(lat=-20.5, lon=110.9),
Point(lat=-20.3, lon=111.2),
Point(lat=-20.0, lon=111.1),
Point(lat=-19.8, lon=111.0),
Point(lat=-19.8, lon=110.8),
Point(lat=-19.9, lon=110.6),
Point(lat=-20.2, lon=110.4),
Point(lat=-20.6, lon=110.3),
Point(lat=-21.2, lon=109.9),
Point(lat=-21.9, lon=109.4),
Point(lat=-22.8, lon=108.8),
Point(lat=-23.9, lon=108.3),
Point(lat=-25.0, lon=107.8),
Point(lat=-26.1, lon=107.8),
Point(lat=-27.3, lon=107.7),
Point(lat=-28.5, lon=108.8),
Point(lat=-29.2, lon=109.6),
Point(lat=-29.8, lon=110.7),
Point(lat=-30.0, lon=112.0)
]
lat_array = np.arange(-40, -9.8, 0.1)
lon_array = np.arange(97.7, 122.0, 0.1)
# below is a basic figure with no adjust, looks horrible
fig = plt.figure()
ax = fig.add_subplot(111)
for indx, pt in enumerate(example_points):
m.scatter(pt.lon, pt.lat, s=20, c='k')
if np.mod(indx, 2) == 0:
my_text = plt.text(pt.lont pt.lat, 'str about this long',
ha='right', va='center', fontsize=10,
fontweight='bold', color='k')
plt.savefig('basic_figure.png')
# below is a very stripped down version of my plot, there are more things plotted near
# the points, but I have removed them for the example purposes.
# the aim is to not have the labels too close to the points, but also not have them go over
# the border of the map
fig = plt.figure()
ax = fig.add_subplot(111)
label_list = []
repel_obj = []
for indx, pt in enumerate(example_points):
m.scatter(pt.lon, pt.lat, s=20, c='k')
if np.mod(indx, 2) == 0:
my_text = plt.text(pt.lon,
pt.lat,
'str this long',
ha='right',
va='center',
fontsize=10,
fontweight='bold',
color='k')
label_list.append(my_text)
# create an area around the points that the labels should not enter
# this is done by creating a fake circle around each point, with alpha=0 so we
# do not see it, normally the plot has additional items plotted near the points
circle_x, circle_y = polygon(pt.lon, pt.lat, 70, 32)
repel_circle = plt.fill(circle_x, circle_y, color='m', alpha=0.0)
repel_obj += repel_circle
# without save_steps or adding ax.draw(r) to adjust_text routine the labels go
# over the border.
adjust_text(label_list,
add_objects=repel_obj,
ax=ax,
force_points=0.5,
force_objects=0.5,
lim=100,
arrowprops=dict(arrowstyle="->", connectionstyle='arc3', color='k',lw=1.0)#,
#save_steps=True
)
plt.savefig('adjust_figure.png')
from adjusttext.
I had to fix some things a bit because it wasn't working, but still, I can't reproduce the problem... m
wasn't defined, so I substituted it for ax
, and there was a comma missing.
I also see that your figsize and/or x/ylim are not standard, is it set to something in your rcparams? You don't specify it here.Or is it all the remnants of you basemap code?
I have to say, I never tested this with basemap, and it is possible that something from it might be at play here...
from adjusttext.
My apologies, I think that I had half-modified the script to remove basemap, but then was running the old script.. stupid mistake.
It seems I also cannot reproduce the issue if basemap is not used. So I guess the issue is related to the use of basemap..
from adjusttext.
OK, no problem. I guess adding draw calls shouldn't harm even without basemap, so maybe it's a good idea if it fixes the basemap situation... Since you have already modified the code, could you please check that the speed isn't affected much compared to the repo version? And if the difference is minimal, maybe submit a PR to introduce this?
from adjusttext.
I ran some speed tests, adding ax.draw(r) changed the average time to run the adjust_text function from ~ 0.5 seconds to ~1 sec.
Instead of just adding this in and slowing the function down, i created an on_basemap argument (default=False) which means the ax.draw(r) will only be called if the user plans to plot on a basemap.
I did a fork and created a pull request. This is the first time I have done that so please let me know if It worked correctly.
from adjusttext.
OK, great, thanks! Looks good to me, I'll merge it.
from adjusttext.
Related Issues (20)
- Time Limit HOT 2
- Altering Data HOT 3
- Please be mindful of the versions HOT 10
- Example of integrating seaborn.object()
- Plotly support? HOT 1
- Feature request: Fix output (specify iteration limit instead of time) HOT 2
- Is the `bioframe` dependency necessary? HOT 3
- Just started not working one day with this error HOT 2
- Version 1.0.3 has a non declared dependency on pandas HOT 1
- force_points key word removed? HOT 2
- Labels misplaced in subplots HOT 1
- Issue with "matplotlib.axes.Axes.annotate" using the arguments "xytext" and "textcoords" HOT 5
- Poor Result when avoiding a polygonal curve HOT 6
- adjustText 1.1 doesn't work properly anymore HOT 6
- Arrows disappear when using cartopy transformation HOT 11
- query_pairs unexpected argument HOT 3
- Numpy 2.0 related issue - use of 'np.Inf`' HOT 3
- update to work with numpy 2.0 HOT 1
- Prevent text overlapping scaled scatter points HOT 3
- avoid crossing of the connector lines HOT 11
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from adjusttext.