fix beamformer and qtimage
add ipy
This commit is contained in:
parent
6973dc619f
commit
bec256bc22
@ -99,12 +99,15 @@ class SoftwareConfig:
|
||||
j = json.loads(path.read_text(encoding='utf-8'))
|
||||
arg_d = dict()
|
||||
for field in dataclasses.fields(SoftwareConfig):
|
||||
try:
|
||||
v = j[field.name]
|
||||
match field.type:
|
||||
case Path():
|
||||
arg_d[field.name] = Path(v)
|
||||
case _:
|
||||
arg_d[field.name] = v
|
||||
except KeyError:
|
||||
pass
|
||||
sc = SoftwareConfig(**arg_d)
|
||||
return sc
|
||||
|
||||
|
||||
@ -5,11 +5,14 @@ import cupy as cp
|
||||
import cv2
|
||||
import zmq
|
||||
|
||||
from flandre.beamformer.das import gen_pwi
|
||||
from flandre.beamformer.dist import direct_dist
|
||||
from flandre.config import C
|
||||
from flandre.nodes.Node import Node
|
||||
from flandre.utils.Config import DeviceConfig
|
||||
from flandre.utils.Msg import BMMsg, ImageArgMsg, SetSeqMetaMsg, Msg, RfFrameWithMetaMsg, BeamformerMsg, \
|
||||
RequestRfFrameMsg, \
|
||||
SeqMetaMsg
|
||||
SeqMetaMsg, RfMatMsg
|
||||
from flandre.utils.RfFile import RfSequenceMeta
|
||||
from flandre.utils.RfMat import RfMat
|
||||
|
||||
@ -28,22 +31,33 @@ class Beamformer(Node):
|
||||
self.muxer_req_socket.connect(C.muxer_rep_socket)
|
||||
self.c.poller.register(self.muxer_req_socket, zmq.POLLIN)
|
||||
|
||||
def process(self, data: RfMat, arg: ImageArgMsg):
|
||||
def process_pwi(self, data: RfMat, arg: ImageArgMsg, pwi):
|
||||
if data is None:
|
||||
return
|
||||
d2 = (data
|
||||
.crop(arg.t_start, arg.t_end)
|
||||
.dct(80, 1500)
|
||||
.call(lambda m: m.astype(cp.int16))
|
||||
.call(pwi)
|
||||
.call(cp.asarray, order='C')
|
||||
.argrelextrema()
|
||||
.conv_guass(b=18 * 0.01)
|
||||
.rotate90()
|
||||
.grey()
|
||||
.cpu()
|
||||
.resize((C.video_width, C.video_height))
|
||||
.watermark()
|
||||
.call(cv2.cvtColor, cv2.COLOR_GRAY2RGBA)
|
||||
# .resize((C.video_width, C.video_height))
|
||||
# .watermark()
|
||||
# .call(cv2.cvtColor, cv2.COLOR_GRAY2RGBA)
|
||||
)
|
||||
self.send(BMMsg(0, d2.__bytes__()))
|
||||
# print(d2.m.dtype)
|
||||
# input()
|
||||
# self.send(BMMsg(0, d2.__bytes__()))
|
||||
self.send(RfMatMsg(d2))
|
||||
|
||||
def loop(self):
|
||||
time.sleep(1)
|
||||
dc = DeviceConfig()
|
||||
pwi,_ = gen_pwi(direct_dist(dc), dc)
|
||||
while True:
|
||||
self.muxer_req_socket.send(b'')
|
||||
r = dict(self.c.poller.poll())
|
||||
@ -66,4 +80,5 @@ class Beamformer(Node):
|
||||
fb1 = cp.frombuffer(s, dtype=cp.int16)
|
||||
seq_meta = RfSequenceMeta.from_name(seq_msg.name)
|
||||
mat = RfMat(fb1.reshape(seq_meta.shape), b_msg.meta, seq_meta)
|
||||
self.process(mat, arg_msg)
|
||||
if seq_meta.mode == RfSequenceMeta.RfSequenceMode.PWI:
|
||||
self.process_pwi(mat, arg_msg, pwi)
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
from PyQt6.QtCore import QByteArray, Qt
|
||||
from PyQt6.QtGui import QImage, QPixmap
|
||||
from PyQt6.QtGui import QImage, QPixmap, QKeyEvent
|
||||
from PyQt6.QtWidgets import QMainWindow, QApplication, QGraphicsPixmapItem, QGraphicsScene
|
||||
|
||||
from flandre.config import C
|
||||
from flandre.nodes.Node import Node
|
||||
from flandre.pyqt.Image import Ui_MainWindow
|
||||
from flandre.pyqt.ZMQReceiver import ZMQReceiver
|
||||
from flandre.utils.Msg import KillMsg, Msg, BMMsg
|
||||
from flandre.utils.Msg import KillMsg, Msg, BMMsg, RfMatMsg, KeyPressMsg
|
||||
|
||||
|
||||
class Adv(QMainWindow, Ui_MainWindow):
|
||||
@ -23,6 +25,24 @@ class Adv(QMainWindow, Ui_MainWindow):
|
||||
self.s = QGraphicsScene()
|
||||
self.s.addItem(self.g)
|
||||
self.graphicsView.setScene(self.s)
|
||||
self.grey = True
|
||||
self.scale = False
|
||||
|
||||
def keyPressEvent(self, a0: QKeyEvent):
|
||||
t = a0.text()
|
||||
match t:
|
||||
case 'm':
|
||||
self.grey = not self.grey
|
||||
case 's':
|
||||
self.scale = not self.scale
|
||||
|
||||
def on_key(self, key):
|
||||
# test for a specific key
|
||||
logging.info(f'{type(key)}')
|
||||
# if key == QtCore.Qt.Key_Return:
|
||||
# print('return key pressed')
|
||||
# else:
|
||||
# print('key pressed: %i' % key)
|
||||
|
||||
def on_zmq_event(self, msg: QByteArray):
|
||||
msg = Msg.decode_msg(msg.data())
|
||||
@ -39,10 +59,33 @@ class Adv(QMainWindow, Ui_MainWindow):
|
||||
)
|
||||
self.g.setPixmap(QPixmap(qImg))
|
||||
self.graphicsView.fitInView(self.s.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio)
|
||||
elif isinstance(msg, RfMatMsg):
|
||||
w = msg.rfmat.m.shape[1]
|
||||
h = msg.rfmat.m.shape[0]
|
||||
if self.grey:
|
||||
d2 = msg.rfmat.grey()
|
||||
qImg = QImage(
|
||||
d2.__bytes__(),
|
||||
w, h, w,
|
||||
QImage.Format.Format_Grayscale8
|
||||
)
|
||||
else:
|
||||
d2 = msg.rfmat.pseudo_color()
|
||||
qImg = QImage(
|
||||
d2.__bytes__(),
|
||||
w, h, 3 * w,
|
||||
QImage.Format.Format_BGR888
|
||||
)
|
||||
|
||||
self.g.setPixmap(QPixmap(qImg))
|
||||
if self.scale:
|
||||
self.graphicsView.fitInView(self.s.sceneRect())
|
||||
else:
|
||||
self.graphicsView.fitInView(self.s.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio)
|
||||
|
||||
|
||||
class ImageQt(Node):
|
||||
topics = [BMMsg]
|
||||
topics = [BMMsg, RfMatMsg, KeyPressMsg]
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
@ -4,7 +4,10 @@ import struct
|
||||
from enum import auto, Enum
|
||||
from pathlib import Path
|
||||
|
||||
from flandre.utils.RfMeta import RfFrameMeta
|
||||
import numpy as np
|
||||
|
||||
# from flandre.utils.RfMat import RfMat
|
||||
from flandre.utils.RfMeta import RfFrameMeta, RfSequenceMeta
|
||||
|
||||
|
||||
class BG(Enum):
|
||||
@ -48,6 +51,8 @@ class BG(Enum):
|
||||
SetDeviceSwitchMsg = auto()
|
||||
DeviceSwitchMsg = auto()
|
||||
HeaderByteMsg = auto()
|
||||
RfMatMsg = auto()
|
||||
KeyPressMsg = auto()
|
||||
|
||||
|
||||
class Msg:
|
||||
@ -134,6 +139,11 @@ class StrMsg(Msg):
|
||||
value: str = ''
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class KeyPressMsg(StrMsg):
|
||||
pass
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class BoolMsg(Msg):
|
||||
value: bool
|
||||
@ -302,6 +312,32 @@ class RfFrameMsg(Msg):
|
||||
)
|
||||
|
||||
|
||||
class RfMatMsg(HeaderByteMsg):
|
||||
|
||||
def __init__(self, rfmat: 'RfMat'):
|
||||
self.rfmat = rfmat
|
||||
|
||||
super().__init__(dict(
|
||||
frame_meta=rfmat.frame_meta.json_str,
|
||||
seq_meta=rfmat.seq_meta.json_str,
|
||||
data_shape=rfmat.m.shape,
|
||||
dtype=str(rfmat.m.dtype),
|
||||
), rfmat.m.tobytes())
|
||||
|
||||
@classmethod
|
||||
def decode(cls, data) -> 'RfMatMsg':
|
||||
from flandre.utils.RfMat import RfMat
|
||||
msg = super(RfMatMsg, cls).decode(data)
|
||||
dt = np.dtype(msg.header['dtype'])
|
||||
mat = np.frombuffer(msg.data, dtype=dt).reshape(msg.header['data_shape'])
|
||||
rfmat = RfMat(
|
||||
mat,
|
||||
RfFrameMeta.from_json_str(msg.header['frame_meta']),
|
||||
RfSequenceMeta.from_json_str(msg.header['seq_meta']),
|
||||
)
|
||||
return RfMatMsg(rfmat)
|
||||
|
||||
|
||||
class RfFrameWithMetaMsg(HeaderByteMsg):
|
||||
@dataclasses.dataclass
|
||||
class Header:
|
||||
@ -327,6 +363,7 @@ class RfFrameWithMetaMsg(HeaderByteMsg):
|
||||
header = cls.Header(**msg.header)
|
||||
return RfFrameWithMetaMsg(header.sender, RfFrameMeta.from_name(header.meta), msg.data, header.is_zip)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class BytesMsg(Msg):
|
||||
value: bytes
|
||||
@ -402,7 +439,11 @@ if __name__ == '__main__':
|
||||
# c2 = c.decode(c.encode())
|
||||
# print(c2.header, c2.data)
|
||||
|
||||
c = RfFrameWithMetaMsg(1, RfFrameMeta(1, 11, 111), b'asdasdasdads',True)
|
||||
print(c.sender, c.meta, c.data, c._header)
|
||||
c2 = c.decode(c.encode())
|
||||
print(c2.sender, c2.meta, c2.data, c2._header)
|
||||
# c = RfFrameWithMetaMsg(1, RfFrameMeta(1, 11, 111), b'asdasdasdads', True)
|
||||
# print(c.sender, c.meta, c.data, c._header)
|
||||
# c2 = c.decode(c.encode())
|
||||
# print(c2.sender, c2.meta, c2.data, c2._header)
|
||||
|
||||
rfmat = RfMat(np.array([1, 2, 3]), RfFrameMeta(), RfSequenceMeta())
|
||||
e = RfMatMsg(rfmat).encode()
|
||||
d = RfMatMsg.decode(e)
|
||||
|
||||
@ -1,7 +1,20 @@
|
||||
import cupyx
|
||||
import cv2
|
||||
import matplotlib
|
||||
import numpy as np
|
||||
import cupy as cp
|
||||
|
||||
import cupyx
|
||||
import cupyx.scipy.fft
|
||||
import cupyx.scipy.ndimage
|
||||
import cupyx.scipy.signal
|
||||
import cv2
|
||||
import scipy
|
||||
import scipy.signal
|
||||
from cupyx.scipy.fft import dctn, idctn
|
||||
from scipy.stats import norm as norms
|
||||
|
||||
|
||||
from flandre.utils.RfFile import RfFrame, RfSequenceMeta
|
||||
from flandre.utils.RfMeta import RfFrameMeta
|
||||
|
||||
@ -74,6 +87,19 @@ class RfMat:
|
||||
m = self.norm().m
|
||||
return self.copy((m * 255).astype(self.p.uint8))
|
||||
|
||||
def pseudo_color(self):
|
||||
m = self.norm().m * 0.7
|
||||
p = self.p
|
||||
h = m
|
||||
s = p.zeros_like(h) + 1
|
||||
v = p.zeros_like(h) + 1
|
||||
hsv = p.stack((h, s, v), axis=2)
|
||||
if p == cp:
|
||||
rgb = matplotlib.colors.hsv_to_rgb(hsv.get())
|
||||
else:
|
||||
rgb = matplotlib.colors.hsv_to_rgb(hsv)
|
||||
return self.copy((rgb * 255).astype(np.uint8))
|
||||
|
||||
def cpu(self):
|
||||
if self.device == 'cpu':
|
||||
return self
|
||||
@ -139,6 +165,57 @@ class RfMat:
|
||||
def rotate90(self):
|
||||
return self.copy(self.p.rot90(self.m, k=3))
|
||||
|
||||
def dct(self, mmin, mmax):
|
||||
dct_ = scipy.fft.dct
|
||||
idct = scipy.fft.idct
|
||||
if self.p == cp:
|
||||
dct_ = cupyx.scipy.fft.dct
|
||||
idct = cupyx.scipy.fft.idct
|
||||
m_dct = dct_(self.m)
|
||||
if self.seq_meta.d() == 2:
|
||||
m_dct[:, mmax:] = 0
|
||||
m_dct[:, :mmin] = 0
|
||||
elif self.seq_meta.d() == 3:
|
||||
m_dct[:, :, mmax:] = 0
|
||||
m_dct[:, :, :mmin] = 0
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
return self.copy(idct(m_dct))
|
||||
|
||||
def argrelextrema(self, axis=1):
|
||||
arg = scipy.signal.argrelextrema
|
||||
m = self.m
|
||||
p = self.p
|
||||
if p == cp:
|
||||
arg = cupyx.scipy.signal.argrelextrema
|
||||
rm = p.zeros_like(m)
|
||||
indies1 = arg(m, p.greater, axis=axis)
|
||||
bl = p.zeros_like(m, dtype=p.bool_)
|
||||
indies2 = arg(m, p.less, axis=axis)
|
||||
bl2 = p.zeros_like(m, dtype=p.bool_)
|
||||
bl[indies1] = True
|
||||
bl2[indies2] = True
|
||||
i1 = bl & (m > 0)
|
||||
i2 = bl2 & (m < 0)
|
||||
idx = i1 | i2
|
||||
rm[idx] = m[idx].__abs__()
|
||||
return self.copy(rm)
|
||||
|
||||
def conv_guass(self, b=0.01, axis=1):
|
||||
cv = scipy.ndimage.convolve1d
|
||||
m = self.m
|
||||
p = self.p
|
||||
if p == cp:
|
||||
cv = cupyx.scipy.ndimage.convolve1d
|
||||
rv = norms(loc=0, scale=b)
|
||||
x2 = np.arange(-1, 1.1, 0.1)
|
||||
w = rv.pdf(x2)
|
||||
if p == cp:
|
||||
w = cp.asarray(w)
|
||||
rm = cv(m, w, axis=axis)
|
||||
return self.copy(rm)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
cp.zeros((1, 2, 3)) + 1
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import dataclasses
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, auto
|
||||
from pathlib import Path
|
||||
from typing import Annotated, get_type_hints
|
||||
|
||||
from attr import dataclass
|
||||
# from attr import dataclass
|
||||
|
||||
COMMIT_KEY = 'COMMIT'
|
||||
|
||||
@ -88,6 +90,19 @@ class RfMeta:
|
||||
def json_str(self):
|
||||
return json.dumps(self.__dict__)
|
||||
|
||||
@classmethod
|
||||
def from_json_str(clz, j: str):
|
||||
j = json.loads(j)
|
||||
meta = clz()
|
||||
for field in dataclasses.fields(clz):
|
||||
v = j[field.name]
|
||||
match v:
|
||||
case None:
|
||||
pass
|
||||
case _:
|
||||
meta.__setattr__(field.name, field.type(v))
|
||||
return meta
|
||||
|
||||
|
||||
@dataclass
|
||||
class RfFrameMeta(RfMeta):
|
||||
@ -129,7 +144,49 @@ class RfSequenceMeta(RfMeta):
|
||||
res *= int(i)
|
||||
return res
|
||||
|
||||
def d(self):
|
||||
return self.shape.__len__()
|
||||
|
||||
@property
|
||||
def json_str(self):
|
||||
d = dict()
|
||||
for field in dataclasses.fields(RfSequenceMeta):
|
||||
v = self.__getattribute__(field.name)
|
||||
match v:
|
||||
case self.RfSequenceMode():
|
||||
d[field.name] = v.name
|
||||
case _:
|
||||
d[field.name] = v
|
||||
return json.dumps(d)
|
||||
|
||||
@classmethod
|
||||
def from_json_str(clz, j: str):
|
||||
j = json.loads(j)
|
||||
meta = RfSequenceMeta()
|
||||
for field in dataclasses.fields(RfSequenceMeta):
|
||||
v = j[field.name]
|
||||
match field.name:
|
||||
case 'mode':
|
||||
meta.mode = RfSequenceMeta.RfSequenceMode[v]
|
||||
case _:
|
||||
if v is None:
|
||||
meta.__setattr__(field.name, None)
|
||||
else:
|
||||
meta.__setattr__(field.name, field.type(v))
|
||||
return meta
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
r = RfSequenceMeta.from_name('asdasd1,S=(64 1501),M=PWI,U=30')
|
||||
# r = RfSequenceMeta.from_name('asdasd1,S=(64 1501),M=PWI,U=30')
|
||||
# print(r)
|
||||
# print(r.json_str)
|
||||
#
|
||||
# r2 = RfSequenceMeta.from_json_str(r.json_str)
|
||||
# print(r2)
|
||||
|
||||
r = RfFrameMeta.from_name('E=1,S=123')
|
||||
print(r)
|
||||
print(r.json_str)
|
||||
|
||||
r2 = RfFrameMeta.from_json_str(r.json_str)
|
||||
print(r2)
|
||||
|
||||
@ -22,8 +22,6 @@ def folder_to_zip(folder: Path):
|
||||
meta.blake2b = b2b
|
||||
print(i, b2b, file, meta.json_str)
|
||||
|
||||
|
||||
|
||||
src = file
|
||||
dst = TEMP_FOLDER / f'{i}.zst'
|
||||
dstj = TEMP_FOLDER / f'{i}.json'
|
||||
@ -34,6 +32,25 @@ def folder_to_zip(folder: Path):
|
||||
subprocess.run(['zip', '-0', '-j', '-r', TEMP_FOLDER.parent / f'{folder.name}.zip', TEMP_FOLDER])
|
||||
|
||||
|
||||
def to_zip(li: list[tuple[Path, 'RfFrameMeta', list[tuple[Path, str]]]], temp_dst: Path, zipdst: Path):
|
||||
shutil.rmtree(temp_dst)
|
||||
temp_dst.mkdir(parents=True, exist_ok=True)
|
||||
for i, (file, meta, farr) in enumerate(li):
|
||||
b2b = hashlib.blake2b(file.read_bytes(), digest_size=4).hexdigest()
|
||||
meta.blake2b = b2b
|
||||
src = file
|
||||
dst = temp_dst / f'{i}.zst'
|
||||
subprocess.run(['zstd', '-f', src, '-o', dst])
|
||||
|
||||
dstj = temp_dst / f'{i}.json'
|
||||
dstj.write_text(meta.json_str)
|
||||
|
||||
for srcf, suffix in farr:
|
||||
dstf = temp_dst / f'{i}{suffix}'
|
||||
shutil.copy(srcf, dstf)
|
||||
subprocess.run(['zip', '-0', '-j', '-r', zipdst, temp_dst])
|
||||
|
||||
|
||||
def zip_to_bytes(file: Path, name: int):
|
||||
return zstd.loads(zipfile.ZipFile(file).open(f'{name}.zst').read())
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ dependencies = [
|
||||
"pyjoystick>=1.2.4",
|
||||
"platformdirs>=4.3.6",
|
||||
"zstd>=1.5.6.7",
|
||||
"matplotlib>=3.10.1",
|
||||
]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
|
||||
30
test/process_leagacy.py
Normal file
30
test/process_leagacy.py
Normal file
@ -0,0 +1,30 @@
|
||||
from pathlib import Path
|
||||
|
||||
from flandre.utils.RfMeta import RfFrameMeta, RfSequenceMeta
|
||||
from flandre.utils.archive import to_zip
|
||||
|
||||
if __name__ == '__main__':
|
||||
# rr = RfSequenceMeta
|
||||
tempdst = Path('/mnt/16T/private_dataset/ustemp')
|
||||
arr = []
|
||||
for (i,
|
||||
file) in enumerate(Path('/mnt/16T/private_dataset/New Folder/steel-top/').glob('*pwi.bin')):
|
||||
file = Path(file)
|
||||
x, y, _ = file.name.split('_')
|
||||
r = RfFrameMeta(encoder=0, robot_x=int(x) * 100, robot_y=int(y) * 100)
|
||||
arr.append((file, r))
|
||||
arr.sort(key=lambda item: (item[1].robot_y, item[1].robot_x))
|
||||
|
||||
arg = []
|
||||
|
||||
for i, item in enumerate(arr):
|
||||
file, meta = item
|
||||
meta.sequence_id = i
|
||||
print(file.name, meta.sequence_id, meta.robot_x, meta.robot_y)
|
||||
pic = file.with_suffix('.png')
|
||||
farr = []
|
||||
if pic.exists():
|
||||
farr.append((pic, '.png'))
|
||||
arg.append((file, meta, farr))
|
||||
|
||||
to_zip(arg, tempdst, Path('/mnt/16T/private_dataset/us/steel-top,U=30,M=PWI,S=(256 1502).zip'))
|
||||
14
test/testcupy.py
Normal file
14
test/testcupy.py
Normal file
@ -0,0 +1,14 @@
|
||||
import json
|
||||
|
||||
import cupy as cp
|
||||
|
||||
import numpy as np
|
||||
|
||||
if __name__ == '__main__':
|
||||
arr = np.array([
|
||||
[1, 2, 3],
|
||||
[1, 2, 3],
|
||||
])
|
||||
print(type(arr.shape))
|
||||
print(np.frombuffer(arr.tobytes(), dtype=np.dtype(str(arr.dtype))).reshape(arr.shape))
|
||||
|
||||
125
uv.lock
125
uv.lock
@ -253,6 +253,27 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/fb/08b3f4bf05da99aba8ffea52a558758def16e8516bc75ca94ff73587e7d3/construct-2.10.70-py3-none-any.whl", hash = "sha256:c80be81ef595a1a821ec69dc16099550ed22197615f4320b57cc9ce2a672cb30", size = 63020 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "contourpy"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/25/c2/fc7193cc5383637ff390a712e88e4ded0452c9fbcf84abe3de5ea3df1866/contourpy-1.3.1.tar.gz", hash = "sha256:dfd97abd83335045a913e3bcc4a09c0ceadbe66580cf573fe961f4a825efa699", size = 13465753 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/37/6b/175f60227d3e7f5f1549fcb374592be311293132207e451c3d7c654c25fb/contourpy-1.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0ffa84be8e0bd33410b17189f7164c3589c229ce5db85798076a3fa136d0e509", size = 271494 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/6a/7833cfae2c1e63d1d8875a50fd23371394f540ce809d7383550681a1fa64/contourpy-1.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805617228ba7e2cbbfb6c503858e626ab528ac2a32a04a2fe88ffaf6b02c32bc", size = 255444 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/b3/7859efce66eaca5c14ba7619791b084ed02d868d76b928ff56890d2d059d/contourpy-1.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade08d343436a94e633db932e7e8407fe7de8083967962b46bdfc1b0ced39454", size = 307628 },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/b2/011415f5e3f0a50b1e285a0bf78eb5d92a4df000553570f0851b6e309076/contourpy-1.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47734d7073fb4590b4a40122b35917cd77be5722d80683b249dac1de266aac80", size = 347271 },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/7d/ef19b1db0f45b151ac78c65127235239a8cf21a59d1ce8507ce03e89a30b/contourpy-1.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ba94a401342fc0f8b948e57d977557fbf4d515f03c67682dd5c6191cb2d16ec", size = 318906 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/99/6794142b90b853a9155316c8f470d2e4821fe6f086b03e372aca848227dd/contourpy-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efa874e87e4a647fd2e4f514d5e91c7d493697127beb95e77d2f7561f6905bd9", size = 323622 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/0f/37d2c84a900cd8eb54e105f4fa9aebd275e14e266736778bb5dccbf3bbbb/contourpy-1.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1bf98051f1045b15c87868dbaea84f92408337d4f81d0e449ee41920ea121d3b", size = 1266699 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/8a/deb5e11dc7d9cc8f0f9c8b29d4f062203f3af230ba83c30a6b161a6effc9/contourpy-1.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:61332c87493b00091423e747ea78200659dc09bdf7fd69edd5e98cef5d3e9a8d", size = 1326395 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/35/7e267ae7c13aaf12322ccc493531f1e7f2eb8fba2927b9d7a05ff615df7a/contourpy-1.3.1-cp312-cp312-win32.whl", hash = "sha256:e914a8cb05ce5c809dd0fe350cfbb4e881bde5e2a38dc04e3afe1b3e58bd158e", size = 175354 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/35/c2de8823211d07e8a79ab018ef03960716c5dff6f4d5bff5af87fd682992/contourpy-1.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:08d9d449a61cf53033612cb368f3a1b26cd7835d9b8cd326647efe43bca7568d", size = 220971 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "croniter"
|
||||
version = "6.0.0"
|
||||
@ -311,6 +332,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/14/11/8bc53cab1466605ba88ba3c7243078a784ee2cd8974f5602a491882af9af/cupy_cuda12x-13.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:88ef1478f00ae252da0026e7f04f70c9bb6a2dc130ba5f1e5bc5e8069a928bf5", size = 69499349 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cycler"
|
||||
version = "0.12.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debugpy"
|
||||
version = "1.8.11"
|
||||
@ -382,6 +412,7 @@ dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "cupy-cuda12x" },
|
||||
{ name = "jupyter" },
|
||||
{ name = "matplotlib" },
|
||||
{ name = "mido", extra = ["ports-rtmidi"] },
|
||||
{ name = "opencv-python" },
|
||||
{ name = "platformdirs" },
|
||||
@ -399,6 +430,7 @@ requires-dist = [
|
||||
{ name = "click", specifier = ">=8.1.8" },
|
||||
{ name = "cupy-cuda12x", specifier = ">=13.3.0" },
|
||||
{ name = "jupyter", specifier = ">=1.1.1" },
|
||||
{ name = "matplotlib", specifier = ">=3.10.1" },
|
||||
{ name = "mido", extras = ["ports-rtmidi"], specifier = ">=1.3.3" },
|
||||
{ name = "opencv-python", specifier = ">=4.10.0.84" },
|
||||
{ name = "platformdirs", specifier = ">=4.3.6" },
|
||||
@ -411,6 +443,23 @@ requires-dist = [
|
||||
{ name = "zstd", specifier = ">=1.5.6.7" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fonttools"
|
||||
version = "4.57.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/03/2d/a9a0b6e3a0cf6bd502e64fc16d894269011930cabfc89aee20d1635b1441/fonttools-4.57.0.tar.gz", hash = "sha256:727ece10e065be2f9dd239d15dd5d60a66e17eac11aea47d447f9f03fdbc42de", size = 3492448 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/98/d4bc42d43392982eecaaca117d79845734d675219680cd43070bb001bc1f/fonttools-4.57.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:889e45e976c74abc7256d3064aa7c1295aa283c6bb19810b9f8b604dfe5c7f31", size = 2751824 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/62/7168030eeca3742fecf45f31e63b5ef48969fa230a672216b805f1d61548/fonttools-4.57.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0425c2e052a5f1516c94e5855dbda706ae5a768631e9fcc34e57d074d1b65b92", size = 2283072 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/82/121a26d9646f0986ddb35fbbaf58ef791c25b59ecb63ffea2aab0099044f/fonttools-4.57.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44c26a311be2ac130f40a96769264809d3b0cb297518669db437d1cc82974888", size = 4788020 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/26/e0f2fb662e022d565bbe280a3cfe6dafdaabf58889ff86fdef2d31ff1dde/fonttools-4.57.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c41ba992df5b8d680b89fd84c6a1f2aca2b9f1ae8a67400c8930cd4ea115f6", size = 4859096 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/44/9075e323347b1891cdece4b3f10a3b84a8f4c42a7684077429d9ce842056/fonttools-4.57.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ea1e9e43ca56b0c12440a7c689b1350066595bebcaa83baad05b8b2675129d98", size = 4964356 },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/28/caa8df32743462fb966be6de6a79d7f30393859636d7732e82efa09fbbb4/fonttools-4.57.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84fd56c78d431606332a0627c16e2a63d243d0d8b05521257d77c6529abe14d8", size = 5226546 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/46/95ab0f0d2e33c5b1a4fc1c0efe5e286ba9359602c0a9907adb1faca44175/fonttools-4.57.0-cp312-cp312-win32.whl", hash = "sha256:f4376819c1c778d59e0a31db5dc6ede854e9edf28bbfa5b756604727f7f800ac", size = 2146776 },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/5d/1be5424bb305880e1113631f49a55ea7c7da3a5fe02608ca7c16a03a21da/fonttools-4.57.0-cp312-cp312-win_amd64.whl", hash = "sha256:57e30241524879ea10cdf79c737037221f77cc126a8cdc8ff2c94d4a522504b9", size = 2193956 },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/27/45f8957c3132917f91aaa56b700bcfc2396be1253f685bd5c68529b6f610/fonttools-4.57.0-py3-none-any.whl", hash = "sha256:3122c604a675513c68bd24c6a8f9091f1c2376d18e8f5fe5a101746c81b3e98f", size = 1093605 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fqdn"
|
||||
version = "1.5.1"
|
||||
@ -827,6 +876,29 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/93/858e87edc634d628e5d752ba944c2833133a28fa87bb093e6832ced36a3e/jupyterlab_widgets-3.0.13-py3-none-any.whl", hash = "sha256:e3cda2c233ce144192f1e29914ad522b2f4c40e77214b0cc97377ca3d323db54", size = 214392 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kiwisolver"
|
||||
version = "1.4.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/82/59/7c91426a8ac292e1cdd53a63b6d9439abd573c875c3f92c146767dd33faf/kiwisolver-1.4.8.tar.gz", hash = "sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e", size = 97538 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/aa/cea685c4ab647f349c3bc92d2daf7ae34c8e8cf405a6dcd3a497f58a2ac3/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d6af5e8815fd02997cb6ad9bbed0ee1e60014438ee1a5c2444c96f87b8843502", size = 124152 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/0b/8db6d2e2452d60d5ebc4ce4b204feeb16176a851fd42462f66ade6808084/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bade438f86e21d91e0cf5dd7c0ed00cda0f77c8c1616bd83f9fc157fa6760d31", size = 66555 },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/26/d6a0db6785dd35d3ba5bf2b2df0aedc5af089962c6eb2cbf67a15b81369e/kiwisolver-1.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b83dc6769ddbc57613280118fb4ce3cd08899cc3369f7d0e0fab518a7cf37fdb", size = 65067 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/ed/1d97f7e3561e09757a196231edccc1bcf59d55ddccefa2afc9c615abd8e0/kiwisolver-1.4.8-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111793b232842991be367ed828076b03d96202c19221b5ebab421ce8bcad016f", size = 1378443 },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/61/39d30b99954e6b46f760e6289c12fede2ab96a254c443639052d1b573fbc/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:257af1622860e51b1a9d0ce387bf5c2c4f36a90594cb9514f55b074bcc787cfc", size = 1472728 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/3e/804163b932f7603ef256e4a715e5843a9600802bb23a68b4e08c8c0ff61d/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b5637c3f316cab1ec1c9a12b8c5f4750a4c4b71af9157645bf32830e39c03a", size = 1478388 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/9e/60eaa75169a154700be74f875a4d9961b11ba048bef315fbe89cb6999056/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:782bb86f245ec18009890e7cb8d13a5ef54dcf2ebe18ed65f795e635a96a1c6a", size = 1413849 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/b3/9458adb9472e61a998c8c4d95cfdfec91c73c53a375b30b1428310f923e4/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc978a80a0db3a66d25767b03688f1147a69e6237175c0f4ffffaaedf744055a", size = 1475533 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/7a/0a42d9571e35798de80aef4bb43a9b672aa7f8e58643d7bd1950398ffb0a/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:36dbbfd34838500a31f52c9786990d00150860e46cd5041386f217101350f0d3", size = 2268898 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/07/1255dc8d80271400126ed8db35a1795b1a2c098ac3a72645075d06fe5c5d/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:eaa973f1e05131de5ff3569bbba7f5fd07ea0595d3870ed4a526d486fe57fa1b", size = 2425605 },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/df/5a3b4cf13780ef6f6942df67b138b03b7e79e9f1f08f57c49957d5867f6e/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a66f60f8d0c87ab7f59b6fb80e642ebb29fec354a4dfad687ca4092ae69d04f4", size = 2375801 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/10/2348d068e8b0f635c8c86892788dac7a6b5c0cb12356620ab575775aad89/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858416b7fb777a53f0c59ca08190ce24e9abbd3cffa18886a5781b8e3e26f65d", size = 2520077 },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/d8/014b89fee5d4dce157d814303b0fce4d31385a2af4c41fed194b173b81ac/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:085940635c62697391baafaaeabdf3dd7a6c3643577dde337f4d66eba021b2b8", size = 2338410 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/72/dfff0cc97f2a0776e1c9eb5bef1ddfd45f46246c6533b0191887a427bca5/kiwisolver-1.4.8-cp312-cp312-win_amd64.whl", hash = "sha256:01c3d31902c7db5fb6182832713d3b4122ad9317c2c5877d0539227d96bb2e50", size = 71853 },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/85/220d13d914485c0948a00f0b9eb419efaf6da81b7d72e88ce2391f7aed8d/kiwisolver-1.4.8-cp312-cp312-win_arm64.whl", hash = "sha256:a3c44cb68861de93f0c4a8175fbaa691f0aa22550c331fefef02b618a9dcb476", size = 65424 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "3.0.2"
|
||||
@ -845,6 +917,31 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matplotlib"
|
||||
version = "3.10.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "contourpy" },
|
||||
{ name = "cycler" },
|
||||
{ name = "fonttools" },
|
||||
{ name = "kiwisolver" },
|
||||
{ name = "numpy" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pillow" },
|
||||
{ name = "pyparsing" },
|
||||
{ name = "python-dateutil" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2f/08/b89867ecea2e305f408fbb417139a8dd941ecf7b23a2e02157c36da546f0/matplotlib-3.10.1.tar.gz", hash = "sha256:e8d2d0e3881b129268585bf4765ad3ee73a4591d77b9a18c214ac7e3a79fb2ba", size = 36743335 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/1d/5e0dc3b59c034e43de16f94deb68f4ad8a96b3ea00f4b37c160b7474928e/matplotlib-3.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:66e907a06e68cb6cfd652c193311d61a12b54f56809cafbed9736ce5ad92f107", size = 8175488 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/81/dae7e14042e74da658c3336ab9799128e09a1ee03964f2d89630b5d12106/matplotlib-3.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b4bb156abb8fa5e5b2b460196f7db7264fc6d62678c03457979e7d5254b7be", size = 8046264 },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/c4/22516775dcde10fc9c9571d155f90710761b028fc44f660508106c363c97/matplotlib-3.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1985ad3d97f51307a2cbfc801a930f120def19ba22864182dacef55277102ba6", size = 8452048 },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/23/c0615001f67ce7c96b3051d856baedc0c818a2ed84570b9bf9bde200f85d/matplotlib-3.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c96f2c2f825d1257e437a1482c5a2cf4fee15db4261bd6fc0750f81ba2b4ba3d", size = 8597111 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/c0/a07939a82aed77770514348f4568177d7dadab9787ebc618a616fe3d665e/matplotlib-3.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35e87384ee9e488d8dd5a2dd7baf471178d38b90618d8ea147aced4ab59c9bea", size = 9402771 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/b6/a9405484fb40746fdc6ae4502b16a9d6e53282ba5baaf9ebe2da579f68c4/matplotlib-3.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:cfd414bce89cc78a7e1d25202e979b3f1af799e416010a20ab2b5ebb3a02425c", size = 8063742 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matplotlib-inline"
|
||||
version = "0.1.7"
|
||||
@ -1076,6 +1173,25 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pillow"
|
||||
version = "11.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/af/cb/bb5c01fcd2a69335b86c22142b2bccfc3464087efb7fd382eee5ffc7fdf7/pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6", size = 47026707 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/40/052610b15a1b8961f52537cc8326ca6a881408bc2bdad0d852edeb6ed33b/pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f", size = 3190185 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/7e/b86dbd35a5f938632093dc40d1682874c33dcfe832558fc80ca56bfcb774/pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b", size = 3030306 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/5c/467a161f9ed53e5eab51a42923c33051bf8d1a2af4626ac04f5166e58e0c/pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d", size = 4416121 },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/73/972b7742e38ae0e2ac76ab137ca6005dcf877480da0d9d61d93b613065b4/pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4", size = 4501707 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/3a/427e4cb0b9e177efbc1a84798ed20498c4f233abde003c06d2650a6d60cb/pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d", size = 4522921 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/7c/d8b1330458e4d2f3f45d9508796d7caf0c0d3764c00c823d10f6f1a3b76d/pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4", size = 4612523 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/2f/65738384e0b1acf451de5a573d8153fe84103772d139e1e0bdf1596be2ea/pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443", size = 4587836 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/c5/e795c9f2ddf3debb2dedd0df889f2fe4b053308bb59a3cc02a0cd144d641/pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c", size = 4669390 },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/ae/ca0099a3995976a9fce2f423166f7bff9b12244afdc7520f6ed38911539a/pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3", size = 2332309 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/18/24bff2ad716257fc03da964c5e8f05d9790a779a8895d6566e493ccf0189/pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941", size = 2676768 },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/bb/e8d656c9543276517ee40184aaa39dcb41e683bca121022f9323ae11b39d/pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb", size = 2415087 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "4.3.6"
|
||||
@ -1188,6 +1304,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/65/858dc1f7f4c65b9e9c8e769019cb156e6b8b96fd7f2f8f1f6bfef8717d95/pyjoystick-1.2.4-py3-none-any.whl", hash = "sha256:773989a5d796d7f32261d25338d583233ddae9a091c0c13c3fc09d250b0870a9", size = 1185266 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.2.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bb/22/f1129e69d94ffff626bdb5c835506b3a5b4f3d070f17ea295e12c2c6f60f/pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be", size = 1088608 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/05/e7/df2285f3d08fee213f2d041540fa4fc9ca6c2d44cf36d3a035bf2a8d2bcc/pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", size = 111120 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyqt6"
|
||||
version = "6.8.0"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user