Skip to content

Commit

Permalink
Merge 86e051a into 30e355e
Browse files Browse the repository at this point in the history
  • Loading branch information
hugohadfield committed Nov 14, 2018
2 parents 30e355e + 86e051a commit c0992a2
Show file tree
Hide file tree
Showing 11 changed files with 469 additions and 15 deletions.
32 changes: 32 additions & 0 deletions clifford/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,22 @@ def compute_blade_representation(bitmap, firstIdx):
return tuple(blade)


@numba.njit
def val_get_left_gmt_matrix(x, k_list, l_list, m_list, mult_table_vals, ndims):
"""
This produces the matrix X that performs left multiplication with x
eg. X@b == (x*b).value
"""
intermed = np.zeros((ndims,ndims))
test_ind = 0
for k in k_list:
j = l_list[test_ind]
i = m_list[test_ind]
intermed[j, i] += mult_table_vals[test_ind] * x[k]
test_ind = test_ind + 1
return intermed


class NoMorePermutations(Exception):
""" No more permutations can be generated.
"""
Expand Down Expand Up @@ -654,6 +670,22 @@ def lcmt_func_generator(self, grades_a=None, grades_b=None, filter_mask=None):
return get_mult_function(self.k_list, self.l_list, self.m_list, self.mult_table_vals, self.gaDims, self.gradeList,
grades_a = grades_a, grades_b = grades_b, filter_mask = filter_mask, product_mask=self.lcmt_prod_mask)

def get_grade_projection_matrix(self, grade):
"""
Returns the matrix M_g that performs grade projection via left multiplication
eg. M_g@A.value = A(g).value
"""
diag_mask = 1.0 * (np.array(self.gradeList) == grade)
return np.diag(diag_mask)

def get_left_gmt_matrix(self, x):
"""
This produces the matrix X that performs left multiplication with x
eg. X@b == (x*b).value
"""
return val_get_left_gmt_matrix(x.value, self.k_list, self.l_list,
self.m_list, self.mult_table_vals, self.gaDims)

def MultiVector(self,*args,**kw):
'''
create a multivector in this layout
Expand Down
68 changes: 67 additions & 1 deletion clifford/io.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,76 @@

import h5py
import numpy as np
import json


def write_json_file(file_name, mv_array, metric, basis_names, compression=True,
transpose=False, sparse=False, support=None, compression_opts=1):
"""
Writes a json ga file of format version 0.0.1
"""
data_dict = {}

# Record the version number
data_dict['version'] = '0.0.1'

# First lets deal with the multivector coefficient data itself
dset_data = {}
if transpose:
dset_data['data'] = mv_array.T.tolist()
dset_data['transpose'] = True
else:
dset_data['data'] = mv_array.tolist()
dset_data['transpose'] = False

if sparse:
dset_data['sparse'] = True
if support is not None:
dset_data['support'] = support.tolist()
else:
raise ValueError('You must specify the support of the multivectors '
'if you explicitly specify sparse storage')
else:
dset_data['sparse'] = False
dset_data['support'] = []

data_dict['dataset'] = dset_data

# Now save the metric
data_dict["metric"] = metric.tolist()

# Now the basis names
data_dict["basis_names"] = [str(s) for s in basis_names]

with open(file_name, "w") as fp:
json.dump(data_dict, fp)


def read_json_file(file_name):
"""
Reads a json ga file of format version 0.0.1
"""
with open(file_name, "r") as fp:
f = json.load(fp)
assert f['version'] == '0.0.1'
data = f['dataset']
transpose = data['transpose']
if transpose:
data_array = np.array(data['data']).T
else:
data_array = np.array(data['data'])
sparse = data['sparse']
if sparse:
support = data['support']
else:
support = None
metric = np.array(f['metric'])
basis_names = np.array(f['basis_names'][:])
return data_array, metric, basis_names, support


def write_ga_file(file_name, mv_array, metric, basis_names, compression=True,
transpose=False, sparse=False, support=False, compression_opts=1):
transpose=False, sparse=False, support=None, compression_opts=1):
"""
Writes a ga file of format version 0.0.1
"""
Expand Down
105 changes: 99 additions & 6 deletions clifford/tools/g3c/GAOnline.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@

from __future__ import print_function
from clifford import grade_obj
from clifford.g3c import *
from clifford.tools.g3c import interpret_multivector_as_object
from clifford.io import read_ga_file
from clifford import MVArray
import json


def interpolate_colors(alpha, rgb_a, rgb_b):
Expand Down Expand Up @@ -69,6 +73,16 @@ def gen_string(self):
return return_string


class ConfPoint():
def __init__(self,mv,color):
self.mv = mv
self.color = color

def gen_string(self):
return_string = 'DrawConfPoint('+str(self.mv)+','+self.color+');'
return return_string


class GAScene():

def __init__(self):
Expand Down Expand Up @@ -99,6 +113,11 @@ def add_euc_point(self,mv,color='rgb(0,0,0)'):
raise ValueError('Input is not a euc_point')
self.add(EucPoint(mv,color))

def add_conf_point(self,mv,color='rgb(0,0,0)'):
if grade_obj(mv) != 1:
raise ValueError('Input is not a conf_point')
self.add(ConfPoint(mv, color))

def add_circle(self,mv,color='rgb(0,0,0)'):
if grade_obj(mv) != 3:
raise ValueError('Input is not a circle')
Expand Down Expand Up @@ -127,6 +146,8 @@ def add_point_pair(self,mv,color='rgb(0,0,0)'):
def add_object(self, mv, mv_type='interp', color='rgb(0,0,0)'):
if mv_type == 'line':
self.add_line(mv, color)
elif mv_type == 'conf_point':
self.add_conf_point(mv, color)
elif mv_type == 'euc_point':
self.add_euc_point(mv, color)
elif mv_type == 'point_pair':
Expand All @@ -153,6 +174,8 @@ def add_object(self, mv, mv_type='interp', color='rgb(0,0,0)'):
if return_val > 0:
if return_val == 1:
self.add_euc_point(mv,color=color)
elif return_val == 2:
self.add_conf_point(mv,color=color)
elif return_val == 3:
self.add_point_pair(mv, color=color)
elif return_val == 4:
Expand All @@ -172,15 +195,85 @@ def add_object_array(self,mv_array,mv_type='interp',color='rgb(0,0,0)'):
for mv in mv_array:
self.add_object(mv, mv_type, color=color)

def save_to_file(self,filename):
def save_to_file(self, filename):
with open(filename,'w') as fobj:
print(self,file=fobj)
print(self, file=fobj)


class GanjaScene:

def draw_objects(mv_array, mv_type='interp', color='rgb(0,0,0)'):
sc = GAScene()
sc.add_object_array(mv_array, mv_type, color=color)
print(sc)
def __init__(self):
self.internal_list = []

def add_object(self, mv, color=int('AA000000', 16), label=None):
if label is not None:
try:
assert isinstance(label, str)
self.internal_list.append(label)
except:
raise ValueError('Labels must be strings')
self.internal_list.append(color)
self.internal_list.append([i for i in mv.value])

def add_objects(self, mv_list, color=int('AA000000', 16), label=None):
if label is not None:
try:
assert isinstance(label, str)
self.internal_list.append(label)
except:
raise ValueError('Labels must be strings')
self.internal_list.append(color)
for mv in mv_list:
self.internal_list.append([i for i in mv.value])

def __repr__(self):
return json.dumps(self.internal_list)

def save_to_file(self, filename):
with open(filename, 'w') as fobj:
print(self, file=fobj)


def draw_objects_ganja(objects, color=int('AA000000', 16)):
"""
Takes a list of multivectors or a .ga file name and draws the multivectors
By default attempts to interpret the type of object unless a mv_type is specified
"""
if isinstance(objects, str):
data_array, metric, basis_names, support = read_ga_file(objects)
mv_list = [layout.MultiVector(value=data_array[i, :]) for i in range(data_array.shape[0])]
sc = GanjaScene()
sc.add_objects(mv_list, color=color)
print(sc)
return sc
elif isinstance(objects, list) or isinstance(objects, MVArray):
sc = GanjaScene()
sc.add_objects(objects, color=color)
print(sc)
return sc
else:
raise ValueError('The input is not a string or a list of objects')


def draw_objects(objects, mv_type='interp', color='rgb(0,0,0)'):
"""
Takes a list of multivectors or a .ga file name and draws the multivectors
By default attempts to interpret the type of object unless a mv_type is specified
"""
if isinstance(objects, str):
data_array, metric, basis_names, support = read_ga_file(objects)
mv_list = [layout.MultiVector(value=data_array[i,:]) for i in range(data_array.shape[0])]
sc = GAScene()
sc.add_object_array(mv_list, mv_type, color=color)
print(sc)
return sc
elif isinstance(objects, list) or isinstance(objects, MVArray):
sc = GAScene()
sc.add_object_array(objects, mv_type, color=color)
print(sc)
return sc
else:
raise ValueError('The input is not a string or a list of objects')


class GAAnimation():
Expand Down

0 comments on commit c0992a2

Please sign in to comment.