Skip to content

Instantly share code, notes, and snippets.

@yunruse
Created December 23, 2020 12:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yunruse/ffc50549e24805b7956b1710454a89de to your computer and use it in GitHub Desktop.
Save yunruse/ffc50549e24805b7956b1710454a89de to your computer and use it in GitHub Desktop.
A hacky script to modify graph locations in Pixelmator
import os
from pathlib import Path
import struct
import sqlite3
HEIGHT = 2400
X_PER_GPA = 5
X_START = {
'CH5_naumova_P_1': 450,
'CH6_P212121': 450,
'CH6_P21c': 450,
'CH7_P_1': 558,
'CH8_P21c': 450,
}
class PXDFile:
def __repr__(self):
return f"PXDFile({self.path})"
def __init__(self, path):
self.path = Path(path)
self.db = sqlite3.connect(self.path / 'metadata.info')
def keyval(name):
return dict(self.db.execute(
f"select key, value from {name};"
).fetchall())
self.meta = keyval('document_meta')
self.info = keyval('document_info')
def _layer(self, ID):
UUID, type_, = self.db.execute(
f"select identifier, type from document_layers where id = {ID};"
).fetchone()
children = self.layers(UUID)
info = dict(self.db.execute(
f"select key, value from layer_info where layer_id = {ID};"
).fetchall())
x, y = struct.unpack('>dd', info['position'][12:])
pos = int(x*2), int(y*2)
w, h = struct.unpack('>dd', info['size'][12:])
size = int(w*2), int(h*2)
name = info['name'][12:]
length, = struct.unpack('i', name[:4])
name = name[4:4+length]
name = name.decode().replace('\x00', '')
return {
'id': ID,
'uuid': UUID,
'type': type_,
'info': info,
'name': name,
'position': pos,
'size': size,
'children': children
}
def layers(self, ID=None):
if ID is None:
ID = 'is null'
elif isinstance(ID, str):
ID = f' = "{ID}"'
else:
raise TypeError('ID must be None or an integer.')
return [self._layer(ID) for (ID, ) in self.db.execute(
"select id from document_layers"
f" where parent_identifier {ID}"
" order by index_at_parent asc;"
).fetchall()]
def __del__(self):
self.db.commit()
self.db.close()
if __name__ == '__main__':
pxd = PXDFile('/Users/yunruse/Documents/University Work/SH Project/graph/phase.pxd')
COORDS = {}
with open('data.csv') as f:
for line in f.readlines():
name, P, T = line.strip().split(',')
COORDS[name] = float(P), float(T)
pxd.db.execute('PRAGMA journal_mode=DELETE')
pxd.db.execute('begin exclusive')
for layer in pxd.layers():
CH_name = layer['name']
if not CH_name.startswith('CH'):
continue
for i in layer['children']:
if i['name'] == 'Border':
(x0, y0), (w, h) = i['position'], i['size']
x0 -= w
y0 -= h
elif i['name'] == 'Experiments':
points = i['children']
for p in points:
exp_name = CH_name + '-' + p['name']
#x, y = p['position']
#P = int((x - x0 - X_START[CH_name]) / X_PER_GPA)
#T = int((y - y0) / h * HEIGHT - 1200)
#print(','.join((exp_name, str(P), str(T))))
P, T = COORDS[exp_name]
T += P / 2
x = P * X_PER_GPA + X_START[CH_name] + x0
y = int((T + 1200) * h / HEIGHT) + y0
pos = b'4-tPtPTP\x10\x00\x00\x00' + struct.pack('>dd', x/2, y/2)
c = pxd.db.cursor()
c.execute(
'update layer_info set value = ? where layer_id = ?'
'and key = "position"', (pos, p['id'])
)
pxd.db.execute('commit')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment