Логарифмические длины при построении стрелок с помощью функции quiver из pyplot

#python #matplotlib #plot #logarithm

#python #matplotlib #построение #логарифм

Вопрос:

Есть ли простой способ логарифмически масштабировать длины стрелок, нарисованных функцией quiver из PyPlot?

Причина в том, что я строю стрелки ветра над сушей и над океаном, тогда как величина ветра над океаном примерно в десять раз выше.

Следовательно, либо стрелки над землей слишком малы, чтобы получить какую-либо информацию от их построения, либо стрелки над океаном настолько велики, что участок слишком переполнен над океаном.

Я уже пытался использовать функцию symlog для логарифмического масштабирования данных, но, похоже, углы создают проблемы. Чтобы подчеркнуть это, вот код для небольшого графика:

 def main():
  lat, lon, u, v = readmulticol2Dfile('test.txt', shape=(9,6))
  # map without logarithmic scaling
  plt.subplot(1,2,1)
  mapproj = bm.Basemap(projection='cyl', llcrnrlon=lon.min(), urcrnrlon=lon.max(), llcrnrlat=lat.min(), urcrnrlat=lat.max())
  mapproj.drawcoastlines()
  mapproj.drawparallels(np.linspace(-20,20,5), labels=[1,0,0,0])
  mapproj.drawmeridians(np.linspace(-80,20,5), labels=[0,0,0,1])
  plt.title('linear')
  plt.quiver(lon, lat, u, v, color='k', units='x')
  # map with logarithmic scaling
  plt.subplot(1,2,2)
  mapproj = bm.Basemap(projection='cyl', llcrnrlon=lon.min(), urcrnrlon=lon.max(), llcrnrlat=lat.min(), urcrnrlat=lat.max())
  mapproj.drawcoastlines()
  mapproj.drawparallels(np.linspace(-20,20,5), labels=[1,0,0,0])
  mapproj.drawmeridians(np.linspace(-80,20,5), labels=[0,0,0,1])
  plt.quiver(lon, lat, symlog(u), symlog(v), color='k', units='x')
  plt.title('logarithmic')
  plt.show()

def readmulticol2Dfile(fname, header=True, delimiter='t', shape=None):
  """reads a multicolumn txt-file and converts it to numpy arrays"""
  a=np.loadtxt(fname).T
  if shape is not None:
    b=[np.zeros(shape=shape)]*4
    for i in xrange(len(a)):    b[i]=np.reshape(a[i],shape)
    return b
  else: return a

def symlog(x):
  """ Returns the symmetric log10 value """
  return np.sign(x) * np.log10(np.abs(x))

if __name__=="__main__":
  main()
  

используя эти данные, сохраненные в test.txt

 # lattitude longitude   u   v
2.145047503739818495e 01    -8.062500000000000000e 01   -5.790064811706542969e 00   2.341136932373046875e-01
2.145047503739818495e 01    -7.312500000000000000e 01   -7.119166374206542969e 00   -1.223894119262695312e 00
2.145047503739818495e 01    -6.562500000000000000e 01   -6.140162467956542969e 00   -1.082292556762695312e 00
2.145047503739818495e 01    -5.812500000000000000e 01   -4.589381217956542969e 00   2.853832244873046875e-01
2.145047503739818495e 01    -5.062500000000000000e 01   -5.221705436706542969e 00   4.221019744873046875e-01
2.145047503739818495e 01    -4.312500000000000000e 01   -5.333521842956542969e 00   6.321525573730468750e-02
1.771996152644742750e 01    -2.812500000000000000e 01   -7.793482780456542969e 00   -3.714616775512695312e 00
1.771996152644742750e 01    -2.062500000000000000e 01   -6.195338249206542969e 00   -6.160417556762695312e 00
1.585470386969487322e 01    -7.687500000000000000e 01   -8.054713249206542969e 00   -1.638355255126953125e-01
1.585470386969487322e 01    -6.937500000000000000e 01   -7.378443717956542969e 00   -2.906990051269531250e-02
1.585470386969487322e 01    -6.187500000000000000e 01   -6.270533561706542969e 00   3.127269744873046875e-01
1.585470386969487322e 01    -5.437500000000000000e 01   -7.410181999206542969e 00   -1.028003692626953125e-01
1.212418712345576566e 01    -3.937500000000000000e 01   -8.221217155456542969e 00   -2.800065994262695312e 00
1.212418712345576566e 01    -3.187500000000000000e 01   -7.579127311706542969e 00   -3.560319900512695312e 00
1.212418712345576566e 01    -2.437500000000000000e 01   -5.761256217956542969e 00   -5.112565994262695312e 00
1.025892816800637597e 01    -8.062500000000000000e 01   -4.789576530456542969e 00   -4.363542556762695312e 00
1.025892816800637597e 01    -7.312500000000000000e 01   -1.818385124206542969e 00   -1.677995681762695312e 00
1.025892816800637597e 01    -6.562500000000000000e 01   -3.078639030456542969e 00   -1.554460525512695312e 00
6.528409401479990493e 00    -5.062500000000000000e 01   -7.822779655456542969e 00   -1.683855056762695312e 00
6.528409401479990493e 00    -4.312500000000000000e 01   -8.200709342956542969e 00   -2.835222244262695312e 00
6.528409401479990493e 00    -3.562500000000000000e 01   -7.456568717956542969e 00   -2.850358963012695312e 00
6.528409401479990493e 00    -2.812500000000000000e 01   -5.878443717956542969e 00   -2.700944900512695312e 00
6.528409401479990493e 00    -2.062500000000000000e 01   -2.720240592956542969e 00   -1.258562088012695312e 00
4.663149706177883935e 00    -7.687500000000000000e 01   1.257298469543457031e 00    -1.143815994262695312e 00
9.326299678379910141e-01    -6.187500000000000000e 01   -6.386976242065429688e-01   -2.507495880126953125e-01
9.326299678379910141e-01    -5.437500000000000000e 01   -2.149439811706542969e 00   -1.390886306762695312e 00
9.326299678379910141e-01    -4.687500000000000000e 01   -5.939478874206542969e 00   -1.460222244262695312e 00
9.326299678379910141e-01    -3.937500000000000000e 01   -6.882838249206542969e 00   -5.959644317626953125e-01
9.326299678379910141e-01    -3.187500000000000000e 01   -6.343287467956542969e 00   -1.565113067626953125e-01
9.326299678379910141e-01    -2.437500000000000000e 01   -5.749537467956542969e 00   3.444652557373046875e-01
-4.663149706177883935e 00   -7.312500000000000000e 01   -7.033824920654296875e-02   -3.654956817626953125e-01
-4.663149706177883935e 00   -6.562500000000000000e 01   -5.674085617065429688e-01   -3.176441192626953125e-01
-4.663149706177883935e 00   -5.812500000000000000e 01   -1.063014030456542969e 00   -1.213550567626953125e-01
-4.663149706177883935e 00   -5.062500000000000000e 01   -1.417994499206542969e 00   -2.028980255126953125e-01
-4.663149706177883935e 00   -4.312500000000000000e 01   -1.486842155456542969e 00   -8.557300567626953125e-01
-4.663149706177883935e 00   -3.562500000000000000e 01   -5.729517936706542969e 00   1.451887130737304688e 00
-8.393668907692383385e 00   -2.062500000000000000e 01   -6.579615592956542969e 00   2.450422286987304688e 00
-1.025892816800637597e 01   -7.687500000000000000e 01   4.018297195434570312e-01    -1.755542755126953125e-01
-1.025892816800637597e 01   -6.937500000000000000e 01   2.187242507934570312e-01    -5.783863067626953125e-01
-1.025892816800637597e 01   -6.187500000000000000e 01   -3.462171554565429688e-01   -8.737964630126953125e-01
-1.025892816800637597e 01   -5.437500000000000000e 01   -4.731702804565429688e-01   -3.200855255126953125e-01
-1.025892816800637597e 01   -4.687500000000000000e 01   -8.545179367065429688e-01   -4.890308380126953125e-01
-1.398944571235667311e 01   -3.187500000000000000e 01   -7.993678092956542969e 00   1.462230682373046875e-01
-1.398944571235667311e 01   -2.437500000000000000e 01   -8.063502311706542969e 00   1.512434005737304688e 00
-1.585470386969487322e 01   -8.062500000000000000e 01   -2.528346061706542969e 00   3.198469161987304688e 00
-1.585470386969487322e 01   -7.312500000000000000e 01   2.924547195434570312e-01    1.297590255737304688e 00
-1.585470386969487322e 01   -6.562500000000000000e 01   -3.598890304565429688e-01   -1.232194900512695312e 00
-1.585470386969487322e 01   -5.812500000000000000e 01   4.196643829345703125e-02    -1.524187088012695312e 00
-1.958521860882233057e 01   -4.312500000000000000e 01   -1.116724967956542969e 00   -3.195972442626953125e-01
-1.958521860882233057e 01   -3.562500000000000000e 01   -5.567896842956542969e 00   -3.761003494262695312e 00
-1.958521860882233057e 01   -2.812500000000000000e 01   -7.378443717956542969e 00   -1.043718338012695312e 00
-1.958521860882233057e 01   -2.062500000000000000e 01   -8.015162467956542969e 00   7.102775573730468750e-02
-2.145047503739818495e 01   -7.687500000000000000e 01   2.352025032043457031e 00    2.376691818237304688e 00
-2.145047503739818495e 01   -6.937500000000000000e 01   2.939915657043457031e 00    1.054914474487304688e 00
  

Но, к сожалению, результат выглядит довольно странно. Длины на самом деле логарифмические, но в некоторых регионах углы ведут себя странно.

Заранее большое спасибо за вашу помощь =)

PS: У меня недостаточно репутации, чтобы добавить здесь цифру или вторую гиперссылку, поэтому я загрузил ее на ftp-сервер, где она будет автоматически удалена через две недели. Вы можете просто получить доступ к рисунку, заменив ‘.txt’ на ‘.png’ в ссылке данных выше.

Ответ №1:

Из того, что я понял, вы могли бы просто масштабировать длины стрелок, прежде чем передавать их. Вот пример

 import matplotlib.pyplot as plt
import numpy as np

def symlog(x):
    """ Returns the symmetric log10 value """
    return np.sign(x) * np.log10(np.abs(x))

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10,5))

# Generate fake data
N = 50
X,Y = np.meshgrid(np.linspace(0, 1, N), np.linspace(0, 1, N))
U = np.random.normal(0, 0.2, size=(50, 50))
V = np.random.normal(0, 0.2, size=(50, 50))

# Set RHS data to be larger than LHS
U[:, N/2:] *= 1000
V[:, N/2:] *= 1000
angles=np.arctan2(V,U)*180.0/np.pi # calculate angles manually

#Without scaling
HEAD_LENGTH = 4
Q = ax1.quiver( X[::3, ::3], Y[::3, ::3], U[::3, ::3], V[::3, ::3],
             color='k', units='x', headaxislength=HEAD_LENGTH)

#With scaling
Q = ax2.quiver( X[::3, ::3], Y[::3, ::3], symlog(U[::3, ::3]), symlog(V[::3, ::3]),
             color='k', units='x', headaxislength=HEAD_LENGTH, angles=angles)

plt.show()
  

введите описание изображения здесь

Слева показаны необработанные данные, а справа я масштабировал длины стрелок, используя symlog() . Это масштабирует величину значений, сохраняя при этом их знак, иначе у вас будут ошибки, регистрирующие отрицательные числа.

Комментарии:

1. Привет, спасибо за вашу помощь! 🙂 Хотя это сработало для вас, логарифмы, похоже, вызывают проблемы с углами. Я отредактировал свой пост с примером использования функции simlog (см. Выше). Можете ли вы воспроизвести мою проблему, используя мои данные и скрипт?

2. Я сомневаюсь в этом, поскольку у меня нет вашего файла данных. Пожалуйста, добавьте короткий полный рабочий пример, например, который будет копировать и вставлять графики создания. Это поможет улучшить ответы, которые вы получаете.

3. Хорошо, я сделал это, вычислив углы вручную и используя ключевое слово «angles» графика quiver. Я предоставляю полный код ниже.

Ответ №2:

Я использовал аналогичный подход к Грегу, когда столкнулся с этой проблемой, но проблема с его настройками вектора, как вы заметили, заключается в том, что они не сохраняют направление стрелок. Для этого вам необходимо настроить U и V в вашем коде на те же факторы, что и ниже:

 def transform(u, v):
    arrow_lengths = np.sqrt(u*u   v*v)
    len_adjust_factor = np.log10(arrow_lengths   1) / arrow_lengths
    return u*len_adjust_factor, v*len_adjust_factor

U2, V2 = transform(U, V)
  

Эта настройка изменяет только длины стрелок, так что новые длины составляют log10 от старых длин.

Примечание: я использую log10(x 1) в отличие от log10 (x) только для того, чтобы функция не меняла знак вывода относительно ввода, и чтобы функция начиналась с точки (0,0).