diff --git a/ModuleFixTarget.py b/ModuleFixTarget.py index e75ed52..63f363f 100644 --- a/ModuleFixTarget.py +++ b/ModuleFixTarget.py @@ -35,8 +35,9 @@ This contains a Widget to handle FixTargetFrames and fiducials, calculate final import logging _log=logging.getLogger(__name__) -import os, pickle, json, yaml,base64 +import json, base64 #, os, pickle, yaml import numpy as np +import pyqtUsrObj as UsrGO import pyqtgraph as pg from PyQt5.QtCore import Qt, QFileInfo, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import ( @@ -75,29 +76,31 @@ class MyJsonEncoder(json.JSONEncoder): #return obj.tolist() elif isinstance(obj, set): return list(obj) - if type(obj) not in (dict,list,str,int): - _log.error('dont know how to json') - return repr(obj) + elif type(obj) not in (dict,list,str,int): + try: + return obj.obj2json(self) + except AttributeError: + _log.error('dont know how to json') + return repr(obj) return json.JSONEncoder.default(self, obj) def MyJsonDecoder(dct): - if isinstance(dct, dict) and '__ndarray__' in dct: + if isinstance(dct, dict): + if '__class__' in dct: + cls=dct.pop('__class__') + cls=UsrGO.__dict__[cls] + obj=cls.__new__(cls) + obj.__init__(**dct) + #try: + # obj.json2obj(dct) + #except AttributeError: + # obj.__init__(**dct) + return obj + elif '__ndarray__' in dct: data = base64.b64decode(dct['__ndarray__']) return np.frombuffer(data[:-1], dct['dtype']).reshape(dct['shape']) return dct -def yaml_repr_numpy(dumper, data): - return dumper.represent_scalar(u'!np_array', u'%s' % repr(data)) -yaml.add_representer(np.ndarray, yaml_repr_numpy) - -def yaml_cnstr_numpy(loader, node): - value = loader.construct_scalar(node) - a=eval(value[6:-1]) - return np.array(a) -yaml.add_constructor(u'!np_array', yaml_cnstr_numpy) - - - class MarkerDelegate(QItemDelegate): def createEditor(self, parent, option, index): @@ -263,8 +266,8 @@ class WndFixTarget(QWidget): #data_folder = cfg.value("folders/last_prelocation_folder", def_folder) data_folder='' if filename is None: - filename, _ = QFileDialog.getOpenFileName(self,"Load yaml data file",None, - "yaml files (*.yaml);;json files (*.json);;pickle files (*.pkl);;text files (*.txt);;all files (*)",) + filename, _ = QFileDialog.getOpenFileName(self,"Load data file",None, + "json files (*.json);;yaml files (*.yaml);;pickle files (*.pkl);;text files (*.txt);;all files (*)",) if not filename: # cancelled dialog return @@ -350,8 +353,8 @@ class WndFixTarget(QWidget): #data_folder = settings.value("folders/last_prelocation_folder") data_folder='' if filename is None: - filename, _ = QFileDialog.getSaveFileName(self,"Soad yaml data file",data_folder, - "yaml files (*.yaml);;json files (*.json);;pickle files (*.pkl);;text files (*.txt);;all files (*)",) + filename, _ = QFileDialog.getSaveFileName(self,"Save data file",data_folder, + "json files (*.json);;yaml files (*.yaml);;pickle files (*.pkl);;text files (*.txt);;all files (*)",) if not filename: return @@ -370,7 +373,7 @@ class WndFixTarget(QWidget): yaml.dump(self._data, f) elif ext=='json': with open(filename, 'w') as f: - json.dump(self._data, f,cls=MyJsonEncoder) + json.dump(self._data, f,cls=MyJsonEncoder, indent=2)#separators=(',', ':') print(self._data) def delete_selected(self): @@ -725,7 +728,6 @@ void itemSelectionChanged() if __name__ == "__main__": import sys - import pyqtUsrObj as UsrGO class Monster(yaml.YAMLObject): yaml_tag = u'!Monster' diff --git a/pyqtUsrObj.py b/pyqtUsrObj.py index 98c7b50..99917da 100644 --- a/pyqtUsrObj.py +++ b/pyqtUsrObj.py @@ -18,7 +18,10 @@ from pyqtgraph.Qt import QtCore, QtGui import numpy as np from PyQt5.QtGui import QPolygon,QPolygonF from PyQt5.QtCore import Qt,QPointF,QLineF -import yaml + +def itr2str(itr): + return '('+', '.join(tuple(map(lambda x:f'{x:.6g}', itr)))+')' + def obj_tree(obj,p=''): obj_info(obj,p) @@ -159,23 +162,19 @@ class Fiducial(pg.ROI): tr.setMatrix(tr.m11(), tr.m12(), tr.m13(), tr.m21(), -tr.m22(), tr.m23(), tr.m31(), tr.m32(), tr.m33()) p.setTransform(tr) - def __repr__(self): - s=f'{self.__class__.__name__}:(pos:{tuple(self.pos())}, size:{tuple(self.size())}, xyz:{self._xyz}}}' + pos='('+', '.join(tuple(map(lambda x: f'{x:.6g}',self.pos())))+')' + s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, xyz:{itr2str(self._xyz)}}}' return s - @staticmethod - def yaml_repr(dumper, data): - m={'pos':(data.pos()),'size':(data.size()),'xyz':(map(float,data._xyz))} - return dumper.represent_mapping(u'!Fiducial', m) - - @staticmethod - def yaml_cnstr(loader, node): - m=loader.construct_mapping(node) - return Fiducial(**m) - -yaml.add_representer(Fiducial, Fiducial.yaml_repr) -yaml.add_constructor(u'!Fiducial', Fiducial.yaml_cnstr) + def obj2json(self,encoder): + jsn= { + '__class__':self.__class__.__name__, + 'pos':tuple(self.pos()), + 'size':tuple(self.size()), + 'xyz':tuple(self._xyz), + } + return jsn class Grid(pg.ROI): @@ -241,26 +240,18 @@ class Grid(pg.ROI): #p.drawRect(0, 0, 1, 1) def __repr__(self): - s=f'{self.__class__.__name__}:(pos:{tuple(self.pos())}, size:{tuple(self.size())}, cnt:{self._cnt}, ficucialScale:{self._fidScl}}}' + s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, cnt:{self._cnt}, ficucialScale:{self._fidScl}}}' return s - @staticmethod - def yaml_repr(dumper, data): - #s=f'{{"pos":{tuple(data.pos())}, "size":{tuple(data.size())}, "cnt":{data._cnt}, "ficucialScale":{data._fidScl}}}' - #return dumper.represent_scalar(u'!Grid', s) - m={'pos':list(data.pos()),'size':list(data.size()),'cnt':list(data._cnt), 'ficucialScale':data._fidScl} - return dumper.represent_mapping(u'!Grid', m) - - @staticmethod - def yaml_cnstr(loader, node): - # value = loader.construct_scalar(node) - # kwargs=eval(value) - # return Grid(**kwargs) - m=loader.construct_mapping(node) - return Grid(**m) - -yaml.add_representer(Grid, Grid.yaml_repr) -yaml.add_constructor(u'!Grid', Grid.yaml_cnstr) + def obj2json(self,encoder): + jsn= { + '__class__':self.__class__.__name__, + 'pos':tuple(self.pos()), + 'size':tuple(self.size()), + 'cnt':self._cnt, + 'ficucialScale':self._fidScl + } + return jsn class Path(pg.ROI): @@ -319,28 +310,24 @@ class Path(pg.ROI): fid=self._fiducial for i in range(fid.shape[0]): - x,y=fid[i,:]#;print(x,y) + x,y=fid[i,:] #;print(x,y) lh=QLineF(x-5*rx,y,x+5*rx,y) lv=QLineF(x, y-5*ry, x, y+5*ry) p.drawLines(lh,lv) def __repr__(self): - s=f'{self.__class__.__name__}:(pos:{tuple(self.pos())}, size:{tuple(self.size())}, cnt:{self._cnt}, ficucialScale:{self._fidScl}}}' + s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, cnt:{self._cnt}, ficucialScale:{self._fidScl}}}' return s - @staticmethod - def yaml_repr(dumper, data): - m={'pos':list(data.pos()),'size':list(data.size()),'cnt':data._cnt, 'ficucialScale':data._fidScl} - return dumper.represent_mapping(u'!Path', m) - - @staticmethod - def yaml_cnstr(loader, node): - m=loader.construct_mapping(node) - return Path(**m) - -yaml.add_representer(Path, Path.yaml_repr) -yaml.add_constructor(u'!Path', Path.yaml_cnstr) - + def obj2json(self,encoder): + jsn= { + '__class__':self.__class__.__name__, + 'pos':tuple(self.pos()), + 'fiducial': repr(self._fiducial), + 'path': repr(self._path), + 'ficucialScale':self._fidScl + } + return jsn class FixTargetFrame(pg.ROI): '''fixed target frame''' @@ -440,7 +427,7 @@ class FixTargetFrame(pg.ROI): p0=np.array(p0) for p1 in ((-120,-120),(120,-120),(0,0),(-120,120),(120,120),): p1=np.array(p1) - x, y=p0+p1 ;print(x,y) + x, y=p0+p1 #;print(x,y) lh=QLineF(x-rx, y, x+rx, y) lv=QLineF(x, y-ry, x, y+ry) p.drawLines(lh, lv) @@ -448,24 +435,17 @@ class FixTargetFrame(pg.ROI): assert('unknown feducial type') def __repr__(self): - s=f'{self.__class__.__name__}:(pos:{tuple(self.pos())}, size:{tuple(self.size())}, dscr:{self._dscr}}}' + s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, dscr:{self._dscr}}}' return s - @staticmethod - def yaml_repr(dumper, data): - #m={'pos':list(data.pos()),'size':list(data.size()),'dscr':repr(data._dscr)} - m={'pos':list(data.pos()),'size':list(data.size())} - return dumper.represent_mapping(u'!FixTargetFrame', m) - - @staticmethod - def yaml_cnstr(loader, node): - m=loader.construct_mapping(node) - #m['dscr']=eval(m['dscr']) - return FixTargetFrame(**m) - -yaml.add_representer(FixTargetFrame, FixTargetFrame.yaml_repr) -yaml.add_constructor(u'!FixTargetFrame', FixTargetFrame.yaml_cnstr) - + def obj2json(self,encoder): + jsn= { + '__class__':self.__class__.__name__, + 'pos':tuple(self.pos()), + 'size':tuple(self.size()), + 'dscr': self._dscr + } + return jsn class TxtROI(pg.ROI):