Compare commits
6 Commits
818a403bf9
...
feature
| Author | SHA1 | Date | |
|---|---|---|---|
| 79c65b480a | |||
| b75a427aad | |||
| 847305ae29 | |||
| c7d24cb61b | |||
| a7cc19c1f9 | |||
| ffb9f743c8 |
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
*.DS_Store
|
||||||
|
*.pyc
|
||||||
|
*.egg-info/
|
||||||
10
README.md
10
README.md
@@ -0,0 +1,10 @@
|
|||||||
|
# Particle Cloud
|
||||||
|
|
||||||
|
A sample library created for students of [Diller Digital's](https://dillerdigital.com) _Software Engineering in the Age of AI_ class.
|
||||||
|
|
||||||
|
**Class Date**
|
||||||
|
|
||||||
|
15 June 2026
|
||||||
|
|
||||||
|
**Students in Attendance**
|
||||||
|
-
|
||||||
46
particlecloud/util.py
Normal file
46
particlecloud/util.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import random
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
FILE_COLUMN_NAMES = [
|
||||||
|
"n", "m", "v1", "v2", "v3", "p1", "p2", "p3",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def write_data_file(filename, n=20, missing_values=False):
|
||||||
|
"""Write a csv file with data
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open(filename, "w") as fp:
|
||||||
|
fp.write(", ".join(FILE_COLUMN_NAMES) + ",\n")
|
||||||
|
for i in range(n):
|
||||||
|
vals = []
|
||||||
|
vals.append(random.gauss(3., 0.5))
|
||||||
|
vals.extend(
|
||||||
|
(
|
||||||
|
random.gauss(0., 25),
|
||||||
|
random.gauss(0., 25),
|
||||||
|
random.gauss(0., 25),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
vals.extend(
|
||||||
|
(
|
||||||
|
random.gauss(0., 1.5),
|
||||||
|
random.gauss(0., 1.5),
|
||||||
|
random.gauss(0., 1.5),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if missing_values:
|
||||||
|
if random.randint(0,10) < 1:
|
||||||
|
idx = random.randint(1, len(vals))
|
||||||
|
vals[idx] = np.nan
|
||||||
|
line = f"{i}, " + ", ".join(f"{v:7.5f}" for v in vals) + ",\n"
|
||||||
|
fp.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
missing_values = sys.argv[-1] == '-m'
|
||||||
|
|
||||||
|
write_data_file("sample_data.csv", n=20, missing_values=True)
|
||||||
115
particlecloud/utils.py
Normal file
115
particlecloud/utils.py
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import csv
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from .stuff import Particle
|
||||||
|
|
||||||
|
|
||||||
|
def _value(text):
|
||||||
|
text = text.strip()
|
||||||
|
if text == "nan":
|
||||||
|
return np.nan
|
||||||
|
return float(text)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_particles_from_csv(filename):
|
||||||
|
particles = []
|
||||||
|
|
||||||
|
with open(filename, newline="") as fp:
|
||||||
|
reader = csv.DictReader(fp, skipinitialspace=True)
|
||||||
|
|
||||||
|
for row in reader:
|
||||||
|
data = {
|
||||||
|
name.strip(): value
|
||||||
|
for name, value in row.items()
|
||||||
|
if name is not None and name.strip()
|
||||||
|
}
|
||||||
|
|
||||||
|
mass = _value(data.get("mass", data.get("m", "1.0")))
|
||||||
|
velocity = [
|
||||||
|
_value(data.get(name, "0.0"))
|
||||||
|
for name in ("v1", "v2", "v3")
|
||||||
|
]
|
||||||
|
position = [
|
||||||
|
_value(data.get(name, "0.0"))
|
||||||
|
for name in ("p1", "p2", "p3")
|
||||||
|
]
|
||||||
|
|
||||||
|
particles.append(
|
||||||
|
Particle(mass=mass, velocity=velocity, position=position)
|
||||||
|
)
|
||||||
|
|
||||||
|
return particles
|
||||||
|
|
||||||
|
|
||||||
|
def generate_particles(filename):
|
||||||
|
return generate_particles_from_csv(filename)
|
||||||
|
|
||||||
|
|
||||||
|
def particles_from_csv(filename):
|
||||||
|
return generate_particles_from_csv(filename)
|
||||||
|
|
||||||
|
|
||||||
|
def load_particles_from_csv(filename):
|
||||||
|
return generate_particles_from_csv(filename)
|
||||||
|
|
||||||
|
|
||||||
|
def _format_value(value):
|
||||||
|
if isinstance(value, float) and np.isnan(value):
|
||||||
|
return "nan"
|
||||||
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
|
def particles_ascii_table(particles):
|
||||||
|
headers = ["mass", "v1", "v2", "v3", "p1", "p2", "p3"]
|
||||||
|
rows = []
|
||||||
|
|
||||||
|
for particle in particles:
|
||||||
|
rows.append(
|
||||||
|
[
|
||||||
|
_format_value(particle.mass),
|
||||||
|
*[_format_value(value) for value in particle.velocity],
|
||||||
|
*[_format_value(value) for value in particle.position],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
widths = [
|
||||||
|
max(len(header), *(len(row[index]) for row in rows))
|
||||||
|
if rows else len(header)
|
||||||
|
for index, header in enumerate(headers)
|
||||||
|
]
|
||||||
|
|
||||||
|
def line(left, fill, join, right):
|
||||||
|
return left + join.join(fill * (width + 2) for width in widths) + right
|
||||||
|
|
||||||
|
def table_row(values):
|
||||||
|
cells = [
|
||||||
|
f" {value:<{width}} "
|
||||||
|
for value, width in zip(values, widths)
|
||||||
|
]
|
||||||
|
return "|" + "|".join(cells) + "|"
|
||||||
|
|
||||||
|
output = [
|
||||||
|
line("+", "-", "+", "+"),
|
||||||
|
table_row(headers),
|
||||||
|
line("+", "-", "+", "+"),
|
||||||
|
]
|
||||||
|
output.extend(table_row(row) for row in rows)
|
||||||
|
output.append(line("+", "-", "+", "+"))
|
||||||
|
|
||||||
|
return "\n".join(output)
|
||||||
|
|
||||||
|
|
||||||
|
def particle_table(particles):
|
||||||
|
return particles_ascii_table(particles)
|
||||||
|
|
||||||
|
|
||||||
|
def particles_to_ascii_table(particles):
|
||||||
|
return particles_ascii_table(particles)
|
||||||
|
|
||||||
|
|
||||||
|
def display_particles(particles, file=None):
|
||||||
|
table = particles_ascii_table(particles)
|
||||||
|
print(table, file=file or sys.stdout)
|
||||||
|
return table
|
||||||
@@ -10,4 +10,4 @@ requires-python = ">=3.10"
|
|||||||
dependencies = []
|
dependencies = []
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
where = ["src"]
|
where = ["."]
|
||||||
|
|||||||
21
tests/data/sample_data.csv
Normal file
21
tests/data/sample_data.csv
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
n, m, v1, v2, v3, p1, p2, p3,
|
||||||
|
0, 2.52850, -6.66968, nan, -32.65983, -0.89960, 0.29473, 0.68066,
|
||||||
|
1, 2.65187, -25.73410, -50.59516, 14.72479, -0.67331, -1.80399, -1.93023,
|
||||||
|
2, 2.22777, 8.42416, 40.67321, -17.48000, 2.48848, -0.07658, -2.04638,
|
||||||
|
3, 2.53149, 24.48020, -49.96775, 17.46839, 0.48338, -2.07946, -4.00152,
|
||||||
|
4, 3.06508, 3.90032, 21.40408, 10.56088, 2.25480, -3.48735, -0.31546,
|
||||||
|
5, 3.51859, -27.61711, -12.14871, 3.06602, -0.32907, 1.21669, -2.07714,
|
||||||
|
6, 3.18332, 19.64087, 18.73822, -12.91103, -0.16126, 0.92019, -0.63486,
|
||||||
|
7, 2.48816, -14.75185, 28.54855, -17.10517, -0.84672, -2.80012, 0.80332,
|
||||||
|
8, 2.77667, -13.70157, -3.96579, -4.41209, -1.05863, 1.42105, -0.75833,
|
||||||
|
9, 3.86158, 23.13040, 11.42271, nan, 0.79455, 1.20608, 0.52254,
|
||||||
|
10, 1.88758, 58.70666, -38.34324, 7.31533, 1.40457, 3.60723, 0.21540,
|
||||||
|
11, 2.83483, 21.44919, -10.00702, -40.62111, -1.36374, 2.34547, 1.38064,
|
||||||
|
12, 3.01481, 34.88795, 8.57083, 30.81856, 0.84668, 0.92361, 0.34169,
|
||||||
|
13, 3.34741, 0.17952, 4.00238, 32.82780, -1.26392, -2.09778, 0.75637,
|
||||||
|
14, 3.01007, -32.21085, 59.03811, -12.70776, -3.19062, 1.39039, 1.86343,
|
||||||
|
15, 3.08330, -2.15503, 27.67618, -34.00539, 2.86129, 2.40962, -1.31612,
|
||||||
|
16, 2.60289, -31.16051, 4.62316, 4.30050, -0.09615, -0.54381, -1.05145,
|
||||||
|
17, 2.07973, -15.44774, 17.68274, 7.37160, 0.80336, 1.05914, -1.38458,
|
||||||
|
18, 2.82383, 2.84181, 10.98406, -6.91943, -1.04686, 0.74401, -1.88755,
|
||||||
|
19, 3.28852, 20.97361, -27.35684, -3.85541, -1.66241, 0.83235, -2.17095,
|
||||||
|
Reference in New Issue
Block a user