From 5706d2ba6cd24b1b168bac98217848b7999f912f Mon Sep 17 00:00:00 2001 From: Alex Liu Date: Wed, 5 Jun 2024 18:09:10 +0800 Subject: [PATCH] delete bak --- bak/phase_space/__init__.py | 0 bak/phase_space/app.py | 66 ------------ bak/phase_space/core/__init__.py | 4 - bak/phase_space/core/measure.py | 28 ----- bak/phase_space/core/sample_point.py | 106 ------------------- bak/phase_space/core/space.py | 84 --------------- bak/phase_space/core/state.py | 51 --------- bak/phase_space/core/view.py | 65 ------------ bak/phase_space/demos/__init__.py | 35 ------- bak/phase_space/demos/fall.py | 13 --- bak/phase_space/demos/fish.py | 18 ---- bak/phase_space/demos/pendulum.py | 16 --- bak/phase_space/demos/spiral.py | 18 ---- bak/phase_space/demos/spring.py | 13 --- bak/phase_space/ui.py | 132 ------------------------ bak/phase_space/utils/__init__.py | 2 - bak/phase_space/utils/common.py | 120 --------------------- bak/phase_space/utils/gradient_color.py | 49 --------- bak/phase_space/views/__init__.py | 5 - bak/phase_space/views/contour.py | 50 --------- bak/phase_space/views/grid.py | 96 ----------------- bak/phase_space/views/pilot.py | 53 ---------- bak/phase_space/views/pole.py | 26 ----- bak/phase_space/views/tip.py | 25 ----- bak/tests/test_00_base.py | 49 --------- bak/tests/test_01_utils.py | 19 ---- bak/tests/test_02_state.py | 26 ----- bak/tests/test_03_space.py | 29 ------ conf/app.yaml | 2 +- conf/problems/01_fall.yaml | 2 +- conf/problems/02_diffuse.yaml | 2 +- doing.py | 14 --- imgui.ini | 4 - play.py | 2 +- {field => src}/__init__.py | 0 {field => src}/app.py | 0 {field => src}/space.py | 15 ++- {field => src}/ui.py | 0 {field => src}/utils/__init__.py | 0 {field => src}/utils/config.py | 0 {field => src}/utils/gradient_color.py | 0 {field => src}/views/__init__.py | 0 {field => src}/views/grid.py | 10 +- {field => src}/views/history.py | 2 +- {field => src}/views/tip.py | 6 +- {field => src}/views/view.py | 0 tests/test_01_utils.py | 2 +- tests/test_02_field.py | 14 +-- 48 files changed, 32 insertions(+), 1241 deletions(-) delete mode 100644 bak/phase_space/__init__.py delete mode 100644 bak/phase_space/app.py delete mode 100644 bak/phase_space/core/__init__.py delete mode 100644 bak/phase_space/core/measure.py delete mode 100644 bak/phase_space/core/sample_point.py delete mode 100644 bak/phase_space/core/space.py delete mode 100644 bak/phase_space/core/state.py delete mode 100644 bak/phase_space/core/view.py delete mode 100644 bak/phase_space/demos/__init__.py delete mode 100644 bak/phase_space/demos/fall.py delete mode 100644 bak/phase_space/demos/fish.py delete mode 100644 bak/phase_space/demos/pendulum.py delete mode 100644 bak/phase_space/demos/spiral.py delete mode 100644 bak/phase_space/demos/spring.py delete mode 100644 bak/phase_space/ui.py delete mode 100644 bak/phase_space/utils/__init__.py delete mode 100644 bak/phase_space/utils/common.py delete mode 100644 bak/phase_space/utils/gradient_color.py delete mode 100644 bak/phase_space/views/__init__.py delete mode 100644 bak/phase_space/views/contour.py delete mode 100644 bak/phase_space/views/grid.py delete mode 100644 bak/phase_space/views/pilot.py delete mode 100644 bak/phase_space/views/pole.py delete mode 100644 bak/phase_space/views/tip.py delete mode 100644 bak/tests/test_00_base.py delete mode 100644 bak/tests/test_01_utils.py delete mode 100644 bak/tests/test_02_state.py delete mode 100644 bak/tests/test_03_space.py delete mode 100644 doing.py rename {field => src}/__init__.py (100%) rename {field => src}/app.py (100%) rename {field => src}/space.py (85%) rename {field => src}/ui.py (100%) rename {field => src}/utils/__init__.py (100%) rename {field => src}/utils/config.py (100%) rename {field => src}/utils/gradient_color.py (100%) rename {field => src}/views/__init__.py (100%) rename {field => src}/views/grid.py (83%) rename {field => src}/views/history.py (94%) rename {field => src}/views/tip.py (75%) rename {field => src}/views/view.py (100%) diff --git a/bak/phase_space/__init__.py b/bak/phase_space/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/bak/phase_space/app.py b/bak/phase_space/app.py deleted file mode 100644 index 557a523..0000000 --- a/bak/phase_space/app.py +++ /dev/null @@ -1,66 +0,0 @@ -from pyglet.window import mouse,Window,key -from pyglet import clock -from .core import * - -from .views import * -from .ui import UI - -class App(Window): - def __init__(self,CFG): - self.CFG=CFG - - w,h=CFG['WIDTH'],CFG['HEIGHT'] - super().__init__(w,h , CFG['TITLE'], resizable=False) - self.set_vsync(False) - clock.schedule_interval(self.update, 1/CFG['FPS']) - self._case_idx=0 - self.demo_names:List[str]=CFG['demo_names'] - self.select_space() - - def select_space(self): - name=self.demo_names[self._case_idx] - self.space,self.views=self.CFG['make_views'](name) - self.reset() - - def on_draw(self): - self.clear() - #name=self.demo_names[self._case_idx] - for v in self.views: - v.render() - self._UI.render() - - def on_key_press(self, symbol, modifiers): - super().on_key_press(symbol, modifiers) - if symbol==key.LEFT or symbol==key.UP : - self._case_idx+=len(self.demo_names)-1 - elif symbol==key.RIGHT or symbol==key.DOWN: - self._case_idx+=1 - self._case_idx%= len(self.demo_names) - self.select_space() - - def on_mouse_press(self,x, y, button, modifiers): - if button & mouse.RIGHT: - self.views[0].on_click(x,y) - - def ui_callback(self,name): - self._case_idx=self.demo_names.index(name) - self.select_space() - - - def reset(self): - self.space.reset() - for v in self.views: - v.reset(self.CFG) - self._UI = UI(self,self.ui_callback, self.demo_names,self.space, "Config", "Set Parameters") - - - def update(self, dt): - for v in self.views: - v.update() - - for key,arg in self.space._args.items(): - if self._UI.settings.get_changed(key): - arg.value=self._UI.settings.get_value(key) - self.reset() - - diff --git a/bak/phase_space/core/__init__.py b/bak/phase_space/core/__init__.py deleted file mode 100644 index 378e049..0000000 --- a/bak/phase_space/core/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .state import * -from .space import * -from .view import * - diff --git a/bak/phase_space/core/measure.py b/bak/phase_space/core/measure.py deleted file mode 100644 index c5e903a..0000000 --- a/bak/phase_space/core/measure.py +++ /dev/null @@ -1,28 +0,0 @@ -from dataclasses import dataclass -from field.utils import Bound - -@dataclass -class Measure: - """坐标轴度量的物理量信息.""" - name: str - bound:Bound - num_sampling:int =10 - - @property - def is_sampling(self): - return self.num_sampling>1 - def __post_init__(self): - self._ds=[self.bound.low] - if self.num_sampling<2: - self.num_sampling=2 - self._step=(self.bound.high-self.bound.low)/(self.num_sampling-1) - for i in range(1,self.num_sampling): - self._ds.append(self.bound.low+i*self._step) - - def value_at(self,index): - return self._step*index+self.bound.low - - def __iter__(self): - yield from self._ds - def __str__(self): - return f'{self.name}({self.bound})' diff --git a/bak/phase_space/core/sample_point.py b/bak/phase_space/core/sample_point.py deleted file mode 100644 index 046db84..0000000 --- a/bak/phase_space/core/sample_point.py +++ /dev/null @@ -1,106 +0,0 @@ -from math import atan,pi -from .state import State -from .space import Space -from .view import View - -class SamplePoint: - - def __init__(self,view:View): - self._space:Space=view._space - self._x_index:int=view._space.get_index(view.x_axis.name) - self._y_index:int=view._space.get_index(view.y_axis.name) - self._state:State=State(view._space.names) - data=list(self._state) - x=view._space.get_measure(self._space.names[self._x_index]) - y=view._space.get_measure(self._space.names[self._y_index]) - data[self._x_index]=x.bound.low+x.bound.distance/2 - data[self._y_index]=y.bound.low+x.bound.distance/2 - self._state.set_data(*data) - self._measure_x=x - self._measure_y=y - - - - self.update() - - - - # def __str__(self): - # return f"({self._data.x:.2f},{self._data.y:.2f})" - - def _update1(self,step):#step is dx - CS=self._space.constraint - state=self._state - data=list(state) - x1=data[self._x_index] - y1=data[self._y_index] - s1=CS(state) - x2,y2=x1+step,y1+step*s1 - data[self._x_index]=x2 - data[self._y_index]=y2 - state.set_data(*data) - s2=CS(state) - x3,y3=x2+step,y2+step*s2 - data[self._x_index]=x3 - data[self._y_index]=y3 - state.set_data(*data) - s3=CS(state) - x4,y4=x3+step,y3+step*s3 - data[self._x_index]=x4 - data[self._y_index]=y4 - state.set_data(*data) - s4=CS(state) - s = (s1+s4+2*(s2+s3))/6.0 - return x1+step,y1+step*s - - def _update2(self,step):#step is delta_time - CS=self._space.constraint - state=self._state - data=list(state) - x1=data[self._x_index] - y1=data[self._y_index] - s1=CS(self._state) - x2,y2=x1+step*y1,y1+step*s1 - data[self._x_index]=x2 - data[self._y_index]=y2 - state.set_data(*data) - s2=CS(state) - x3,y3=x2+step*y2,y2+step*s2 - data[self._x_index]=x3 - data[self._y_index]=y3 - state.set_data(*data) - s3=CS(state) - x4,y4=x3+step*y3,y3+step*s3 - data[self._x_index]=x4 - data[self._y_index]=y4 - state.set_data(*data) - s4=CS(state) - - s = (s1+s4+2*(s2+s3))/6.0 - return x1+step*y1,y1+step*s - - def update(self): - step:float=self._space.arg_value('step') - x,y=0,0 - if self._space._isFirstOrder: - x,y=self._update1(step) - else: - x,y=self._update2(step) - #x,y=self._space.limit([x,y]) - data=list(self._state) - data[self._x_index]=self._measure_x.bound.limit(x,False) - data[self._y_index]=self._measure_y.bound.limit(y,False) - self._state.set_data(*data) - - - @property - def state(self): - return self._state - - - # @property - # def degree(self): - # #x=self._state[self._x_index] - # #y=self._state[self._y_index] - # a = -atan(self._space.constraint(self._state)) #todo - # return a*180.0/pi \ No newline at end of file diff --git a/bak/phase_space/core/space.py b/bak/phase_space/core/space.py deleted file mode 100644 index 8737868..0000000 --- a/bak/phase_space/core/space.py +++ /dev/null @@ -1,84 +0,0 @@ -from typing import Dict,List -from abc import ABC, abstractmethod -from ..utils import ArgInfo -from .state import * -from .measure import * -class Space(ABC): - def __init__( - self, - measures: List[Measure], - isFirstOrder=True - ): - self._sample_point=None - self._name=type(self).__name__ - self._isFirstOrder=isFirstOrder - self._description='' - self._names=[m.name for m in measures] - #print(self.names) - self._measures:Dict[str,Measure]={m.name:m for m in measures} - #self.set_description() - - self._args:Dict[str,ArgInfo]={'step':ArgInfo('step',0.05,0.01,0.5,0.01)} - self.config_args() - self.reset() - - def get_state_zero(self)->State: - return State(' '.join(self.names)) - - def get_index(self,name)->int: - return self._names.index(name) - - - def get_measure(self,name)->Measure: - for k in self._measures.keys(): - if name==k: - #print(self._measures[name]) - return self._measures[name] - @property - def name(self)->str: - return self._name - @property - def names(self)->List[str]: - return self._names - - def clone(self,state): - return self.get_state_zero().set_data(*state) - - def reset(self): - pass - - def limit(self,xs,fix=False): - rt=[] - for i,m in enumerate(self._measures): - rt.append(m.bound.limit(xs[i],fix)) - return rt - - - def arg_value(self,name:str)->float: - return self._args[name].value - - - def set_args(self,args:List[ArgInfo]): - for arg in args: - self._args[arg.name]=arg - - @property - def sample_point(self): - return self._sample_point - @sample_point.setter - def sample_point(self,val): - self._sample_point=val - @property - def description(self): - return self._description - - @description.setter - def description(self,desc:str): - self._description=desc - - def config_args(self): - pass - - @abstractmethod - def constraint(self,state:State)->float: - pass \ No newline at end of file diff --git a/bak/phase_space/core/state.py b/bak/phase_space/core/state.py deleted file mode 100644 index 16ee198..0000000 --- a/bak/phase_space/core/state.py +++ /dev/null @@ -1,51 +0,0 @@ -from collections import namedtuple - -class State: - ID=1 - def __init__(self,field_names:str='x1 x2 x3'): - typeName=f'S{State.ID}' - - self._VectorType=namedtuple(typeName,field_names) - self._fields=self._VectorType._fields - State.ID+=1 - #print(typeName,len(self._fields)) - self._data=self._VectorType._make([0]*len(self._fields)) - @property - def data(self)->namedtuple: - return self._data - @property - def fields(self): - return self._fields - - def __getitem__(self, index): - return self._data[index] - - def __getattr__(self, name): - return self.value(name) - - def value(self,name): - had=hasattr(self._data,name) - if had : - return getattr(self._data,name) - - - def __iter__(self): - yield from self._data - - def set_data(self,*ds): - self._data=self._VectorType._make(ds) - return self - - # def set_value(self,name,val): - # had=hasattr(self._data,name) - # if had: - # setattr(self._data,name,val) - - -if __name__ == "__main__": - p=State('x y') - p.set_data(1,2) - assert 1==p[0] and 2==p[1] - assert 1==p.value('x') and 2==p.value('y') - assert [1,2]==list(p) - assert 1==p.x and 2==p.y diff --git a/bak/phase_space/core/view.py b/bak/phase_space/core/view.py deleted file mode 100644 index d3731f0..0000000 --- a/bak/phase_space/core/view.py +++ /dev/null @@ -1,65 +0,0 @@ -from abc import ABC, abstractmethod -from ..utils import * -from .state import * -from pyglet import shapes,graphics -from phase_space.core import Measure,Space,ArgInfo - - - -class View(ABC): - def __init__(self,space:Space,axis:str=None): - #self._batch = graphics.Batch() - self._space:Space=space - ms=space.names - if axis is None: - ms=space.names[:2] - - else: - ms=axis.split(' ') - - #print(ms) - self.x_axis:Measure=space.get_measure(ms[0]) - self.y_axis:Measure=space.get_measure(ms[1]) - - - def get_vec_zero(self): - ns=f'{self.x_axis.name},{self.y_axis.name}' - return State(ns) - - def on_click(self,sx,sy): - pass - #@abstractmethod - def update(self): - pass - - def reset(self,cfg): - self._batch = graphics.Batch() - w,h=cfg['WIDTH'],cfg['HEIGHT'] - self._viewport=Viewport(Point(0,0),Size(w,h)) - - ox,oy=self._viewport.start - kx=w/self.x_axis.bound.distance - ky=h/self.y_axis.bound.distance - lx,ly=self.x_axis.bound.low,self.y_axis.bound.low - self._ox,self._oy=ox,oy - self._kx,self._ky=kx,ky - self._lx,self._ly=lx,ly - self._w,self._h=w,h - - - def render(self): - self._batch.draw() - - def get_space_pos(self,sx,sy): - x=(sx-self._ox)/self._kx+self._lx - y=(sy-self._oy)/self._ky+self._ly - return x,y - - def get_pos(self,x,y): - x=self.x_axis.bound.limit(x) - y=self.y_axis.bound.limit(y) - sx=self._ox+(x-self._lx)*self._kx - sy=self._oy+(y-self._ly)*self._ky - return round(sx),round(sy) - - diff --git a/bak/phase_space/demos/__init__.py b/bak/phase_space/demos/__init__.py deleted file mode 100644 index 98b7c0d..0000000 --- a/bak/phase_space/demos/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -from os import listdir -from os.path import dirname, basename -from importlib import import_module -from inspect import isclass -from ..core import Space - -# Get a list of all Python files in the same directory as this file -module_names = [basename(f)[:-3] for f in listdir(dirname(__file__)) if f[-3:] == ".py" and not f.endswith("__init__.py")] - -classes=[] -cls_map={} -for module_name in module_names: - module = import_module('phase_space.demos.'+module_name) - _cs=[getattr(module, cls) for cls in dir(module) ] - #print(_cs) - for c in _cs: - if isclass(c) and issubclass(c,Space) and c.__name__ != 'Space': - classes.append(c) - cls_map[c.__name__]=c - #print(f'import module:{module_name}') -print(cls_map.keys()) -def make_space(name,*args): - return cls_map[name](*args) -demo_names=[cls.__name__ for cls in classes] -# nowants=['ArgInfo', 'Space', 'State'] -# for item in nowants: -# demo_names.remove(item) -# Add all class names to __all__ variable -__all__ = ['demo_names','make_space'] -__all__.extend(demo_names) - -globals().update({cls.__name__: cls for cls in classes}) - - - diff --git a/bak/phase_space/demos/fall.py b/bak/phase_space/demos/fall.py deleted file mode 100644 index f3b5338..0000000 --- a/bak/phase_space/demos/fall.py +++ /dev/null @@ -1,13 +0,0 @@ -from ..core.space import Space,ArgInfo -from ..core import State -class Fall(Space): - - def config_args(self): - self.set_args([ArgInfo('a',10,1,10,0.1,'a:acceleration'),ArgInfo('k',2,1,3,0.1,'k:air damp')]) - self.description='t:time v:velocity | & dv/dt=a-kv' - - - - def constraint(self,xs:State): - return self.arg_value('a')-self.arg_value('k')*xs.velocity - diff --git a/bak/phase_space/demos/fish.py b/bak/phase_space/demos/fish.py deleted file mode 100644 index 61d6554..0000000 --- a/bak/phase_space/demos/fish.py +++ /dev/null @@ -1,18 +0,0 @@ -from ..core.space import Space,ArgInfo - -class Fish(Space): - def config_args(self): - self.set_args([ - ArgInfo('a',5,3,5,0.1,'a:Reproductive Rate'), - ArgInfo('b',1,0.5,2,0.1,'b:Resource Limits'), - ArgInfo('h',0.1,0,1.0,0.1,'h:Harvest') - ]) - self.description='y:fish amount | dy/dt=ay-by^2-h' - - - def constraint(self,state): - t,y=state - return self.arg_value('a')*y-self.arg_value('b')*y*y-self.arg_value('h') - - - diff --git a/bak/phase_space/demos/pendulum.py b/bak/phase_space/demos/pendulum.py deleted file mode 100644 index 30dc9bb..0000000 --- a/bak/phase_space/demos/pendulum.py +++ /dev/null @@ -1,16 +0,0 @@ -from ..core.space import Space,ArgInfo,State -from math import sin - -class Pendulum(Space): - - def config_args(self): - self.set_args([ArgInfo('a',2,1,5,0.2,'a:acceleration'),ArgInfo('b',1,0,3,0.2,'damp')]) - self.description="q:angle v:angle velocity | v'=-a.sin(q)-b.v" - - - - def constraint(self,state:State): - x,y=state - return -self.arg_value('a')*sin(x)-self.arg_value('b')*y - - diff --git a/bak/phase_space/demos/spiral.py b/bak/phase_space/demos/spiral.py deleted file mode 100644 index f7f3b4c..0000000 --- a/bak/phase_space/demos/spiral.py +++ /dev/null @@ -1,18 +0,0 @@ -from ..core.space import Space,ArgInfo -from ..core import State -from math import sin,cos,log -class Spiral(Space): - - def config_args(self): - self.set_args([ArgInfo('k',2,1,3,0.1,'k:scale'),ArgInfo('r',0,0,3,0.1,'r:init ridus')]) - self.description='time:t,x,y,z | z=k.t,R=r+ln(1+z) x=R.cos(t) y=R.sin(t)' - - - - def constraint(self,s:State): - t,x,y,z=s - z=self.arg_value('k')*t - R=self.arg_value('r')+log(1+z) - x=R*cos(t) - y=R*sin(t) - s.set_data(t,x,y,z) \ No newline at end of file diff --git a/bak/phase_space/demos/spring.py b/bak/phase_space/demos/spring.py deleted file mode 100644 index 9861b35..0000000 --- a/bak/phase_space/demos/spring.py +++ /dev/null @@ -1,13 +0,0 @@ -from ..core import Space,ArgInfo,State - -class Spring(Space): - - def config_args(self): - self.set_args([ArgInfo('b',4,0.1,6,0.2,'b:Spring strength'),ArgInfo('k',0,0,5,0.5,'k:damp')]) - self.description="t:time x:pos v:velocity | v'+k.v+b.x=0" - - - - def constraint(self,state:State):#time,pos,vol - return -self.arg_value('k')*state.velocity-self.arg_value('b')*state.pos - diff --git a/bak/phase_space/ui.py b/bak/phase_space/ui.py deleted file mode 100644 index 07f9d59..0000000 --- a/bak/phase_space/ui.py +++ /dev/null @@ -1,132 +0,0 @@ -from typing import List -import imgui -from imgui.integrations.pyglet import create_renderer -from .core import Space -class UISetting: - def __init__( - self, - dtype: str, - type: str, - value: float, - min: float = None, - max: float = None, - step: float = None, - format: str = None, - name: str = "No name", - description: str = None, - ): - self.dtype = dtype - self.type = type - self.value = value - self.min = min - self.max = max - self.step = step - self.format = format - self.name = name - self.description = description - self.changed = False - - def set_config(self): - desc=self.name if self.description is None else self.description - """Missing some combinations""" - if self.dtype == "int" and self.type == "input": - self.changed, self.value = imgui.input_int(self.description, self.value) - elif self.dtype == "float" and self.type == "slider": - self.changed, self.value = imgui.slider_float( - desc, self.value, self.min, self.max, self.format, self.step - ) - else: - raise Exception("Unknown type") - return self - - -class UISettings(List): - def __init__(self, field:Space): - settings=[] - for key,arg in field._args.items(): - settings.append(UISetting( - dtype="float", - type="slider", - value=arg.value, - min=arg.low, - max=arg.high, - step=arg.step, - format="%.2f", - name=key, - description=arg.desc - )) - #arg.attach(self.callbak) - self.settings = settings - self._index = 0 - #def callbak(self,arg): - # print(arg.name) - - def __iter__(self): - for setting in self.settings: - yield setting - - def __setitem__(self, item, value): - self.settings[item] = value - return self - - def get_value(self, name: str): - out = None - for setting in self.settings: - if setting.name == name: - out = setting.value - if out is None: - raise KeyError("Setting not found") - return out - - def get_changed(self, name: str): - out = None - for setting in self.settings: - if setting.name == name: - out = setting.changed - if out is None: - raise KeyError("Setting not found") - return out - - -class UI: - def __init__( - self, window, cb, demo_names:List[str], space:Space,name: str = "Config", text: str = "Set pendulum parameters" - ): - settings: UISettings=UISettings(space) - imgui.create_context() - self.impl = create_renderer(window) - self.settings = settings - self.name = name - self.text = text - self.demo_names=demo_names - self.callback=cb - - - - - def render(self):#,names:List[str]=['C1','C2'],cb=None - imgui.new_frame() - imgui.begin(self.name) - imgui.text(self.text) - - N=len(self.demo_names) - data=[False]*N - for idx,na in enumerate(self.demo_names): - if imgui.radio_button(na, data[idx]): - if self.callback!=None: - imgui.end() - imgui.end_frame() - #imgui.render() - self.callback(na) - return - if idxself.high: - rt=self.high if isFixed else self.low - return rt - - def __str__(self): - return f'{self.low}->{self.high}' - @property - def distance(self): - return self.high-self.low -@dataclass -class ArgInfo: - """可变参数定义.""" - name: str - value: float - low: float - high: float - step: float=0 - desc: str=None - ''' - def __init__( - self, - name: str, - value: float, - low: float, - high: float, - step: float=0 - - ): - self._name=name - self._value=value - self._low=low - self._high=high - self._step=step - self._callbaks=[] - - def notify(self): - for cb in self._callbaks: - cb(self) - def attach(self,callback): - self._callbaks.append(callback) - - def detach(self,callback): - self._callbaks.remove(callback) - @property - def name(self): - return self._name - @property - def low(self): - return self._low - @property - def high(self): - return self._high - @property - def step(self): - return self._step - @property - def value(self): - return self._value - @value.setter - def value(self,val): - self._value=val - self.notify() - ''' - -if __name__ == "__main__": - p=Point(1,2) - assert [1,2]==list(p) - p.y=9.9 - assert [1,9.9]==list(p) - \ No newline at end of file diff --git a/bak/phase_space/utils/gradient_color.py b/bak/phase_space/utils/gradient_color.py deleted file mode 100644 index fad5407..0000000 --- a/bak/phase_space/utils/gradient_color.py +++ /dev/null @@ -1,49 +0,0 @@ -import numpy as np -from typing import Callable,List - -__all__=['linear_gradient','RGB_to_hex'] - -def hex_to_RGB(hex:str)->List: - ''' "#FFFFFF" -> [255,255,255] ''' - # Pass 16 to the integer function for change of base - return [int(hex[i:i+2], 16) for i in range(1,6,2)] - - -def RGB_to_hex(RGB:List)->str: - ''' [255,255,255] -> "#FFFFFF" ''' - # Components need to be integers for hex to make sense - RGB = [int(x) for x in RGB] - return "#"+"".join(["0{0:x}".format(v) if v < 16 else - "{0:x}".format(v) for v in RGB]) -# def color_dict(gradient): -# ''' Takes in a list of RGB sub-lists and returns dictionary of -# colors in RGB and hex form for use in a graphing function -# defined later on ''' -# return {"hex":[RGB_to_hex(RGB) for RGB in gradient], -# "r":[RGB[0] for RGB in gradient], -# "g":[RGB[1] for RGB in gradient], -# "b":[RGB[2] for RGB in gradient]} - - -def linear_gradient(start_hex:str, finish_hex:str="#FFFFFF", n:int=10)->List: - ''' returns a gradient list of (n) colors between - two hex colors. start_hex and finish_hex - should be the full six-digit color string, - inlcuding the number sign ("#FFFFFF") ''' - # Starting and ending colors in RGB form - s = hex_to_RGB(start_hex) - f = hex_to_RGB(finish_hex) - # Initilize a list of the output colors with the starting color - RGB_list = [s] - # Calcuate a color at each evenly spaced value of t from 1 to n - for t in range(1, n): - # Interpolate RGB vector for color at the current value of t - curr_vector = [ - int(s[j] + (float(t)/(n-1))*(f[j]-s[j])) - for j in range(3) - ] - # Add it to our list of output colors - RGB_list.append(curr_vector) - - return RGB_list - #return color_dict(RGB_list) \ No newline at end of file diff --git a/bak/phase_space/views/__init__.py b/bak/phase_space/views/__init__.py deleted file mode 100644 index 9ed9dc6..0000000 --- a/bak/phase_space/views/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .grid import Grid -from .tip import Tip -from .pole import Pole -from .pilot import Pilot -from .contour import Contour diff --git a/bak/phase_space/views/contour.py b/bak/phase_space/views/contour.py deleted file mode 100644 index 3693fd0..0000000 --- a/bak/phase_space/views/contour.py +++ /dev/null @@ -1,50 +0,0 @@ -from math import pi -from pyglet import shapes -from ..core import * -from math import exp -class Contour(View): - N_COLORS:int = 8 - def reset(self,cfg): - super().reset(cfg) - self._colors=linear_gradient('#0000FF','#FF0000',self.N_COLORS) - names=self._space.names - self.t_axis=self._space.get_measure(names[0]) - self.x_axis=self._space.get_measure(names[1]) - self.y_axis=self._space.get_measure(names[2]) - w,h=self._viewport.size - ns=self.t_axis.num_sampling - #DX=self.t_axis.bound.distance/(ns-1) - step=self._space.arg_value('step')#DX/10# - self._ps=[] - self.add_line(step) - - def add_line(self,step): - time_bound=self.t_axis.bound - x_bound=self.x_axis.bound - y_bound=self.y_axis.bound - - state=self._space.get_state_zero() - - t=0 - dx=0 - while t=DX: - dx=0 - x,y=self.get_pos(data[0],data[1]) - #print(t2,x,y) - self._ps.append(shapes.Circle(x,y,2,color=c,batch=self._batch)) - - - - - - - - - - diff --git a/bak/phase_space/views/pole.py b/bak/phase_space/views/pole.py deleted file mode 100644 index df7e661..0000000 --- a/bak/phase_space/views/pole.py +++ /dev/null @@ -1,26 +0,0 @@ -from math import pi -from pyglet import shapes -from ..core import * - - -class Pole(View): - def reset(self,cfg): - super().reset(cfg) - self.sp=self._space.sample_point - w,h=cfg['WIDTH'],cfg['HEIGHT'] - L=9.8/(self._space.arg_value('a')**2) - self.rope=shapes.Rectangle(w/2,h-50,6,60*L,color=(205, 155, 44),batch=self._batch) - self.rope.anchor_x=self.rope.width/2 - self.rope.anchor_y=self.rope.height - - - - def update(self): - if not hasattr(self,'sp') : - return - - px,_=self.sp.state - self.rope.rotation=px/pi*180 - - - diff --git a/bak/phase_space/views/tip.py b/bak/phase_space/views/tip.py deleted file mode 100644 index 35d81f7..0000000 --- a/bak/phase_space/views/tip.py +++ /dev/null @@ -1,25 +0,0 @@ - -from pyglet import shapes -from pyglet.text import Label -from ..core import * -class Tip(View): - def reset(self,cfg): - super().reset(cfg) - w,h=self._viewport.size - self._tips=[ - Label('TIP: ',font_size=20,color=(0,255,8,210),x=20,y=64,batch=self._batch), - Label('arrow key show next case',font_size=18,color=(5,235,28,210),x=20,y=44,batch=self._batch), - Label('right mouse reset the ball',font_size=18,color=(5,235,28,210),x=20,y=24,batch=self._batch) - ] - - self._name=Label(self._space.name,font_size=20,x=20,y=h-30,batch=self._batch) - self._ylable=Label(self.y_axis.name,font_size=20,x=20,y=h/2,batch=self._batch) - self._xlable=Label(self.x_axis.name,font_size=20,x=w/2,y=20,batch=self._batch) - - # self._bg=shapes.Rectangle(w*0.38,h-20,w*0.618,40,color=(0, 0, 0),batch=self._batch) - # self._bg.anchor_x=0 - # self._bg.anchor_y=self._bg.height - self._desc=Label(self._space.description,font_size=20,color=(255,0,0,255),x=w*0.382,y=h-32,batch=self._batch) - - - diff --git a/bak/tests/test_00_base.py b/bak/tests/test_00_base.py deleted file mode 100644 index 52248d4..0000000 --- a/bak/tests/test_00_base.py +++ /dev/null @@ -1,49 +0,0 @@ -import pytest -import random -from math import atan2,pi -parametrize_gamma = pytest.mark.parametrize("gamma",[.1, 0.5, 1.0]) -parametrize_n = pytest.mark.parametrize("n", [1, 10, 20]) - -@pytest.fixture -def eps(): - return 10e-3 - -@parametrize_gamma -@parametrize_n -def test_parametrize(eps, gamma, n): - random.seed(eps) - data=gamma*n - #print(gamma,n,data) # pytest -s - assert 0.1<=data<=20 - -def test_complex(): - z1=1+1j - z2=complex(1,1) - - #print(z1) - assert z1.real==1 and z1.imag==1 - assert z1==z2 - - z=complex(3,4) - assert abs(z)==5 - -def test_math(): - a=atan2(0,0) - assert 0==a - a=atan2(0,1) - assert 0==a - a=atan2(1,1) - assert pi/4==a - a=atan2(1,0) - assert pi/2==a - a=atan2(1,-1) - assert pi/2+pi/4==a - a=atan2(0,-1) - assert pi==a - a=atan2(-1,-1) - assert -pi/2-pi/4==a - a=atan2(-1,0) - assert -pi/2==a - a=atan2(-1,1) - assert -pi/4==a - \ No newline at end of file diff --git a/bak/tests/test_01_utils.py b/bak/tests/test_01_utils.py deleted file mode 100644 index b773f68..0000000 --- a/bak/tests/test_01_utils.py +++ /dev/null @@ -1,19 +0,0 @@ -import sys -from os import path -dir=path.abspath(path.dirname(__file__) + './..') -sys.path.append(dir) -from field.utils import Bound,linear_gradient,RGB_to_hex - -def test_bound(): - b1=Bound() - assert 1==b1.distance - b2=Bound(-1,1) - assert 2==b2.distance - b3=Bound(-100,100) - assert 200==b3.distance - -def test_linear_gradient(): - cs=linear_gradient('#100000','#300000',3) - assert 3==len(cs) - assert '#100000'==RGB_to_hex(cs[0]) and '#300000'==RGB_to_hex(cs[2]) - assert '#200000'==RGB_to_hex(cs[1]) \ No newline at end of file diff --git a/bak/tests/test_02_state.py b/bak/tests/test_02_state.py deleted file mode 100644 index 69eba33..0000000 --- a/bak/tests/test_02_state.py +++ /dev/null @@ -1,26 +0,0 @@ -import sys -from os import path -dir=path.abspath(path.dirname(__file__) + './..') -sys.path.append(dir) -from phase_space.core import State -def test_unpack(): - data=[1,2,3,4] - print(*data) - - -def test_state(): - d=State('x y') - d.set_data(1,2) - assert 1==d[0] and 2==d[1] - assert 1==d.value('x') and 2==d.value('y') - assert [1,2]==list(d) - assert 1==d.x and 2==d.y - - v2=State('time pos') - assert [0,0]==list(v2) - v2.set_data(1.1,2.2) - assert [1.1,2.2]==list(v2) - assert 1.1==v2.time and 2.2==v2.pos - - - diff --git a/bak/tests/test_03_space.py b/bak/tests/test_03_space.py deleted file mode 100644 index 402f94a..0000000 --- a/bak/tests/test_03_space.py +++ /dev/null @@ -1,29 +0,0 @@ -import sys -from os import path -dir=path.abspath(path.dirname(__file__) + './..') -sys.path.append(dir) -from phase_space.core import State -from phase_space.demos.fall import FALL - -def test_space(): - names=FALL.names - assert 2==len(names) and 'time'==names[0] and 'velocity'==names[1] - time=FALL.get_measure('time') - assert time.bound.distance==(time.bound.high-time.bound.low) - - assert time.bound.limit(11)==0 - - state=FALL.get_state_zero() - assert 0==state.time and 0==state.velocity - - state.set_data(1,1.23) - assert 1==state.time and 1.23==state.velocity - - acc=FALL.constraint(state) - assert acc>0 - -def test_clone(): - state=FALL.get_state_zero() - s2=state.set_data(11,22) - assert 11==s2.time and 22==s2.velocity - \ No newline at end of file diff --git a/conf/app.yaml b/conf/app.yaml index 23f03d5..8a4015e 100644 --- a/conf/app.yaml +++ b/conf/app.yaml @@ -3,7 +3,7 @@ HEIGHT: 600 FPS: 60 TITLE: Space View -cells_side: 24 +cells_side: 30 animate_time: 6 #second normalize: true ball_pos: [0,0.98] # normalize coordinate, [1,1] correspond to the top right corner of the screen diff --git a/conf/problems/01_fall.yaml b/conf/problems/01_fall.yaml index fb8c57f..a27deed 100644 --- a/conf/problems/01_fall.yaml +++ b/conf/problems/01_fall.yaml @@ -4,4 +4,4 @@ V: 9.8-k*Y X: ["time",0,60] #name,min,max Y: ["speed",40,60] args: - k: ["drag coefficient",0.2,0,1] #name,value,min,max \ No newline at end of file + k: ["drag coefficient",0.2,0,0.27] #name,value,min,max \ No newline at end of file diff --git a/conf/problems/02_diffuse.yaml b/conf/problems/02_diffuse.yaml index 645537f..dbce8bc 100644 --- a/conf/problems/02_diffuse.yaml +++ b/conf/problems/02_diffuse.yaml @@ -4,4 +4,4 @@ V: k*(20-Y) X: ["time",0,60] #name,min,max Y: ["temperature",0,40] args: - k: ["coefficient of conduction",0.2,0,10] #name,value,min,max \ No newline at end of file + k: ["coefficient of conduction",0.2,0,0.7] #name,value,min,max \ No newline at end of file diff --git a/doing.py b/doing.py deleted file mode 100644 index 64d0a08..0000000 --- a/doing.py +++ /dev/null @@ -1,14 +0,0 @@ -from field.utils import load_config,get_config -from field import Space - -if __name__ == "__main__": - # names=load_config() - # assert '01_fall'==names[0] - # cfg=get_config(names[0]) - # fd=Space(cfg) - # assert 'time'==fd.x_name - # assert 'speed'==fd.y_name - # print(fd.ball_pos) - # x,y=fd.ball_pos - #print(fd.move(x,y)) - print(round(1.4)) \ No newline at end of file diff --git a/imgui.ini b/imgui.ini index ad96920..1e68044 100644 --- a/imgui.ini +++ b/imgui.ini @@ -3,8 +3,4 @@ Pos=364,41 Size=646,120 Collapsed=0 -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 diff --git a/play.py b/play.py index aea2aec..e591ec4 100644 --- a/play.py +++ b/play.py @@ -1,5 +1,5 @@ import pyglet -from field.app import App +from src.app import App def main(): App() diff --git a/field/__init__.py b/src/__init__.py similarity index 100% rename from field/__init__.py rename to src/__init__.py diff --git a/field/app.py b/src/app.py similarity index 100% rename from field/app.py rename to src/app.py diff --git a/field/space.py b/src/space.py similarity index 85% rename from field/space.py rename to src/space.py index 2df92de..d487a1b 100644 --- a/field/space.py +++ b/src/space.py @@ -58,7 +58,7 @@ def reset(self): U=func1(X,Y,*ds) V=func2(X,Y,*ds) - v_interp = interp2d(xs, ys, V, kind='cubic') + v_interp = interp2d(xs, ys, V, kind='linear') #kind='cubic' u_interp = interp2d(xs, ys, np.ones_like(V)*U, kind='linear') ball_x=x1+(x2-x1)*cfg.ball_pos[0] ball_y=y1+(y2-y1)*cfg.ball_pos[1] @@ -83,15 +83,22 @@ def get_direction(self,x,y): dy = v/(dis+1e-10) return dx,dy - def next_pos(self,x,y,scale=0.5): + def next_pos_dir(self,x,y,scale=0.5): k= self.steps[0]*scale,self.steps[1]*scale dx,dy=self.get_direction(x,y) pos = self.clip(x+dx*k[0],y+dy*k[1]) - return pos + return pos,np.array([dx,dy]) def update(self): x,y=self.ball_pos - pos = self.next_pos(x,y,self.STEP_K) + pos1,dir1 = self.next_pos_dir(x,y,self.STEP_K) + pos2,dir2 = self.next_pos_dir(pos1[0],pos1[1],self.STEP_K) + pos3,dir3 = self.next_pos_dir(pos2[0],pos2[1],self.STEP_K) + pos4,dir4 = self.next_pos_dir(pos3[0],pos3[1],self.STEP_K) + dir=(dir1+2*dir2+2*dir3+dir4)/6 + k= self.steps[0]*self.STEP_K,self.steps[1]*self.STEP_K + dx,dy=dir + pos = self.clip(x+dx*k[0],y+dy*k[1]) self.trajectory.push(pos) self.ball_pos[0]=pos[0] self.ball_pos[1]=pos[1] diff --git a/field/ui.py b/src/ui.py similarity index 100% rename from field/ui.py rename to src/ui.py diff --git a/field/utils/__init__.py b/src/utils/__init__.py similarity index 100% rename from field/utils/__init__.py rename to src/utils/__init__.py diff --git a/field/utils/config.py b/src/utils/config.py similarity index 100% rename from field/utils/config.py rename to src/utils/config.py diff --git a/field/utils/gradient_color.py b/src/utils/gradient_color.py similarity index 100% rename from field/utils/gradient_color.py rename to src/utils/gradient_color.py diff --git a/field/views/__init__.py b/src/views/__init__.py similarity index 100% rename from field/views/__init__.py rename to src/views/__init__.py diff --git a/field/views/grid.py b/src/views/grid.py similarity index 83% rename from field/views/grid.py rename to src/views/grid.py index fc41b96..e53cffb 100644 --- a/field/views/grid.py +++ b/src/views/grid.py @@ -2,7 +2,7 @@ from pyglet import shapes,graphics from pyglet.text import Label -from field.utils import linear_gradient +from src.utils import linear_gradient from math import pi,atan2,tan,exp,inf from .view import View class Grid(View): @@ -36,8 +36,8 @@ def reset(self): for j in range(N): x=self._space.x_limit[0]+j*dx y=self._space.y_limit[0]+i*dy - x1,y1=self._space.next_pos(x,y,1.2) - self.add_line_segment(x,y,x1,y1) + pos,_=self._space.next_pos_dir(x,y,1.2) + self.add_line_segment(x,y,*pos) def add_line_segment(self,x,y,x1,y1): @@ -46,8 +46,8 @@ def add_line_segment(self,x,y,x1,y1): k=0.618 x1=x*(1-k)+x2*k y1=y*(1-k)+y2*k - line1=shapes.Line(x,y,x1,y1,color=(223, 223, 223),batch=self._batch) - line2=shapes.Line(x1,y1,x2,y2,color=(250, 50, 34),batch=self._batch) + line1=shapes.Line(x,y,x1,y1,color=(255, 250, 203),batch=self._batch) + line2=shapes.Line(x1,y1,x2,y2,color=(0, 250, 0),batch=self._batch) self._lines.append((line1,line2)) diff --git a/field/views/history.py b/src/views/history.py similarity index 94% rename from field/views/history.py rename to src/views/history.py index 6e21b54..ebc8720 100644 --- a/field/views/history.py +++ b/src/views/history.py @@ -39,7 +39,7 @@ def reset(self): x,y=self._space.ball_pos N=self._space.trajectory.max_size for i in range(N): - self.cs.append(shapes.Circle(x,y,3,color=(255, 255, 0),batch=self._batch)) + self.cs.append(shapes.Circle(x,y,1,color=(255, 255, 0),batch=self._batch)) diff --git a/field/views/tip.py b/src/views/tip.py similarity index 75% rename from field/views/tip.py rename to src/views/tip.py index c19aba4..35138d2 100644 --- a/field/views/tip.py +++ b/src/views/tip.py @@ -6,9 +6,9 @@ def reset(self): w,h=self.w,self.h self._tips=[ - Label('TIP: ',font_size=20,color=(0,255,8,210),x=20,y=64,batch=self._batch), - Label('arrow key show next case',font_size=18,color=(5,235,28,210),x=20,y=44,batch=self._batch), - Label('right mouse reset the ball',font_size=18,color=(5,235,28,210),x=20,y=24,batch=self._batch) + Label('TIP: ',font_size=20,color=(245,255,8,210),x=20,y=64,batch=self._batch), + Label('arrow key show next case',font_size=18,color=(245,235,28,210),x=20,y=44,batch=self._batch), + Label('right mouse reset the ball',font_size=18,color=(245,235,28,210),x=20,y=24,batch=self._batch) ] self._ylable=Label(self._space.y_name,font_size=20,x=20,y=h/2,batch=self._batch) diff --git a/field/views/view.py b/src/views/view.py similarity index 100% rename from field/views/view.py rename to src/views/view.py diff --git a/tests/test_01_utils.py b/tests/test_01_utils.py index 1ac749b..63f635a 100644 --- a/tests/test_01_utils.py +++ b/tests/test_01_utils.py @@ -2,7 +2,7 @@ from os import path dir=path.abspath(path.dirname(__file__) + './..') sys.path.append(dir) -from field.utils import linear_gradient,RGB_to_hex +from src.utils import linear_gradient,RGB_to_hex def test_linear_gradient(): diff --git a/tests/test_02_field.py b/tests/test_02_field.py index 40c73fa..35204c8 100644 --- a/tests/test_02_field.py +++ b/tests/test_02_field.py @@ -3,18 +3,18 @@ dir=path.abspath(path.dirname(__file__) + './..') sys.path.append(dir) -from field.utils import load_config,get_config -from field import Space +from src.utils import load_config,get_config +from src import Space def test_space(): names=load_config() assert '01_fall'==names[0] cfg=get_config(names[0]) - fd=Space(cfg) - assert 'time'==fd.x_name - assert 'speed'==fd.y_name - x,y=fd.ball_pos - x1,y1=fd.move(x,y) + space=Space(cfg) + assert 'time'==space.x_name + assert 'speed'==space.y_name + x,y=space.ball_pos + x1,y1=space.next_pos_dir(x,y) assert x1>x and y1