Данные о скорости биннинга и их усреднение - PullRequest
0 голосов
/ 11 июля 2020

Итак, я запускаю симуляцию, в которой частицы взаимодействуют друг с другом и со стенами. Вот фрагмент, который записывал данные частицы (количество временных шагов, скорость-x, скорость-y, скорость-z, позиция-x, позиция-y, позиция-z) в отдельные файлы для каждой частицы в большом количестве. временных шагов (увеличивается на 1000). Сейчас у меня 15 частиц, но в будущем их будет больше.

N_max = sim.getNumTimeSteps()
particleData = [ [] for x in range(len(sim.getParticleList()))]
for n in range (N_max):
    sim.runTimeStep()
    if (n%1000==0):
        particles = sim.getParticleList()
        for i in range(len(sim.getParticleList())):
            x, y, z = particles[i].getVelocity()
            x2, y2, z2 =  particles[i].getPosition()
            particleData[i].append( (n, x, y, z, x2, y2, z2) )
for i in range(len(sim.getParticleList())):
    with open("{0:d}.dat".format(i), "w") as f:
        for j in particleData[i]:
            f.write("%f : %f,%f,%f : %f,%f,%f \n" % (j[0], j[1], j[2], j[3], j[4], j[5], j[6]))
sim.exit()

В моей симуляции верхняя стена зафиксирована, а нижняя сдвинута (движется). Мне интересно разделить мою симуляцию на полосы на основе y-позиции. Итак, если это 10 единиц в направлении y, я хочу разбить его на 10 полос шириной 1. Я пытаюсь собрать скорости частиц на этих полосах (для сравнения скоростей в зависимости от близости к какой стене), которые я затем усредню и построю на графике с помощью matplotlib.

Я очень новичок в Python, так что кто-то очень хороший порекомендовал мне использовать binning. IE для каждого временного шага, после считывания положения и скорости частицы, я должен проверить, где находится эта частица по оси y. Как мне это сделать - добавить в список частиц для каждой корзины? И они рекомендовали хранить среднюю информацию в другом массиве. Я много погуглил по биннингу, но я поражен всем, что могут делать numpy и scipy, поэтому эти сложные / продвинутые примеры для меня потеряны. Это лучший способ go об этом? Все это имеет смысл?!

Это все, что я получил с чтением данных частицы ...

for i in range(10):
    with open("{}.dat".format(i),'r') as csvfile:
        data = csv.reader(csvfile, delimiter=',')
        y2 = []
        for row in data:
            y2.append(float(row[5]))

тогда я предполагаю, что биннинг происходит, помещая y2 между определенными значениями? как if (n / 10) <= y2 <= ((n+1) / 10):?

Вот пример файлов dat:

0.0: 0.999900, -0.999900,0.0: -6.999000, -7.001000,0.0
1000.0: -1.617575, -0.927360,0.0: -6.032388, -9.007120,0.0
2000.0: -1.019145, -0.939388,0.0: -3.059924, -9.008897,0.0
3000.0: 0.654350, -0.560711,0.0: -4.575242, -9.242543,0.0
4000.0: 0.592084,0.509928,0.0: -3.952575, -9.275643,0.0
5000.0: 2.288733,0.0,0.0: -3.038456, -10.0,0.0
et c до конца моделирование, n = 20000

  • Каждый файл принадлежит отдельной частице, поэтому он показывает движение и скорость этой частицы по временным шагам.
  • Я моделирую 15 частиц, поэтому у меня есть 15 файлов.
  • Для полосы, я хочу, чтобы все частицы были в этой полосе в любое время.
    • Я усредню эти числа позже.
  • Если область моделирования 10x10, частицы будут где-то между y = 0 и y = 10.

1 Ответ

0 голосов
/ 11 июля 2020

Это не - [Pandas, Numpy, SciPy] решение. Если в какой-то момент в будущем время обработки станет раздражающим, вы можете вникнуть в них - это кривая обучения. Есть и другие преимущества, особенно с Pandas - последующий анализ может быть проще с Pandas - Но вы, вероятно, можете проводить весь анализ и без него.

  • Для полос мне нужны все частицы находятся в этой полосе в любое время.

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

import csv
from collections import namedtuple
Particle = namedtuple('Particle',('name','t','x','y','z','x2','y2','z2'))

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

# positions in example data are all negative
bins = {-0:[],-1:[],-2:[],-3:[],-4:[],-5:[],-6:[],-7:[],-8:[],-9:[]}

Используйте модуль csv для чтения всех файлов; сделать частицы; положить их в урны.

for name in range(3):
    with open(f'{name}.dat') as f:
        reader = csv.reader(f,delimiter=':')
        # example row
        # 0.0 : 0.999900,-0.999900,0.0 : -6.999000,-7.001000,0.0
        for t,vel,pos in reader:
            t = float(t)
            x,y,z = map(float, vel.split(','))
            x2,y2,z2 = map(float, pos.split(','))
            p = Particle(name,t,x,y,z,x2,y2,z2)
            y = int(p.y2)
            #print(f'{y}:{p}')
            bins[y].append(p)

Частично bins на основе случайных данных.

{-9: [Particle(name=1, t=1000.0, x=1.09185, y=2.13655, z=-1.96046, x2=-8.74504, y2=-9.89888, z2=-9.49985),...],
 -8: [Particle(name=0, t=5000.0, x=1.2371, y=1.10508, z=-0.9939, x2=-9.47672, y2=-8.90004, z2=-8.06145),
      Particle(name=2, t=7000.0, x=-0.82952, y=0.14332, z=-0.3446, x2=-2.76384, y2=-8.14855, z2=-7.2325)],
 -7: [...,Particle(name=2, t=12000.0, x=1.06694, y=0.02654, z=-2.93894, x2=-8.62668, y2=-7.93497, z2=-6.18243)],
 -6: [Particle(name=0, t=3000.0, x=0.01791, y=-2.67168, z=-1.39907, x2=-6.00256, y2=-6.64951, z2=-6.35569),...,
      Particle(name=2, t=18000.0, x=2.41593, y=-2.27558, z=-1.1414, x2=-6.90592, y2=-6.42374, z2=-9.67672)],
 -5: [...],
 -4: [...],
 ...}

Создатель случайных данных.

import numpy as np
import csv
def make_data(q=3):
    for n in range(q):
        data = np.random.random((21,6))
        np.add(data, [-.5,-.5,-.5,0,0,0], out=data)
        np.multiply(data,[6,6,6,-10,-10,-10],out=data)
        np.round_(data,5,data)
        t = np.linspace(0,20000,21)
        data = np.hstack((t[:,None],data))
        with open(f'{n}.dat', 'w', newline='') as f:
            writer = csv.writer(f,delimiter=':')
            writer.writerows(data.tolist())

Если в будущем вам понадобятся более тонкие полосы, скажем сотые доли единиц, просто умножьте на этот коэффициент.

>>> factor = 100
>>> y2 = -1.20513
>>> int(y2*factor)
-120
>>> d = {n:[] for n in range(0,-10*factor,-1)}
>>> d[int(y2*factor)].append(str(y2))
>>> d[-120]
['-1.20513']
>>>
...