Skip to content

Commit

Permalink
Merge branch 'master' of github.com:DamCB/tyssue
Browse files Browse the repository at this point in the history
  • Loading branch information
glyg committed Nov 22, 2016
2 parents f7217cf + 5938a9d commit 60d0470
Show file tree
Hide file tree
Showing 14 changed files with 2,247 additions and 112 deletions.
Binary file added doc/illus/face_subdivision.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,812 changes: 1,812 additions & 0 deletions doc/illus/face_subdivision.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 6 additions & 21 deletions tyssue/config/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,13 @@

from ..json_parser import load_spec
import os

CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))

def core_spec():
"""Solver default specification for scipy.optimize.minimize gradient
descent
.. code-block::
{
'face': {
'is_alive': true,
},
'edge': {
'face': 0,
'srce': 0,
'trgt': 0
},
'vert': {
'is_active': true,
}
}
def bulk_spec():
"""
Default settings to perform edge subdivisions,
see tyssue.io.point_cloud.py
"""
specfile = os.path.join(CURRENT_DIR, 'core.json')
specfile = os.path.join(CURRENT_DIR, 'bulk.json')
return load_spec(specfile)
13 changes: 13 additions & 0 deletions tyssue/config/subdiv/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import os
from ..json_parser import load_spec


CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))

def bulk_spec():
"""
Default settings to perform edge subdivisions,
see tyssue.io.point_cloud.py
"""
specfile = os.path.join(CURRENT_DIR, 'bulk.json')
return load_spec(specfile)
7 changes: 7 additions & 0 deletions tyssue/config/subdiv/bulk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

{"start": 0.0,
"stop": 1.0,
"gamma": 1.0,
"density": 4,
"noise": 0,
"scale": 1}
116 changes: 49 additions & 67 deletions tyssue/core/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,32 +218,6 @@ def settings(self, key, value): #pragma: no cover
# So this method is not actually called.
self.specs['settings'][key] = value

@classmethod
def from_points(cls, identifier, points,
indices_dict, specs,
points_dataset='vert'):
'''
TODO: not sure this works as expected with the new indexing
'''

raise NotImplementedError('Epithelium.from_points() is not implemented and should not be used.') #pragma: no cover

# if points.shape[1] == 2:
# coords = ['x', 'y']
# elif points.shape[1] == 3:
# coords = ['x', 'y', 'z']
# else:
# raise ValueError('the `points` argument must be'
# ' a (Nv, 2) or (Nv, 3) array')

# datasets = {}
# for key, spec in specs.items():
# datasets[key] = make_df(index=indices_dict[key],
# spec=spec)
# datasets[points_dataset][coords] = points

# return cls.__init__(identifier, datasets, specs, coords=coords)

def update_specs(self, new, reset=False):

spec_updater(self.specs, new)
Expand Down Expand Up @@ -298,8 +272,6 @@ def edge_idx(self):
# Should it return self.edge_df.index instead ?
return self.edge_df[self.element_names]



@property
def Nc(self):
if 'cell' in self.data_names:
Expand Down Expand Up @@ -347,20 +319,50 @@ def _upcast(self, idx, df):
upcast.index = self.edge_df.index
return upcast

def upcast_cols(self, element, columns):
"""Syntactic sugar to upcast from the
epithelium datasets.
Parameters
----------
element: {'srce'|'trgt'|'face'|'cell'}
corresponding self.edge_df column over which to index
if element is 'srce' or 'trgt', the upcast data will be
taken form self.vert_df
columns: index
the column(s) to be taken from the input dataset.
"""
if element in ['srce', 'trgt']:
dataset = 'vert'
else:
dataset = element
return self._upcast(self.edge_df[element],
self.datasets[dataset][columns])

def upcast_srce(self, df):
''' Reindexes input data to self.edge_idx
by repeating the values for each source entry
'''
return self._upcast(self.e_srce_idx, df)
return self._upcast(self.edge_df['srce'], df)

def upcast_trgt(self, df):
return self._upcast(self.e_trgt_idx, df)
''' Reindexes input data to self.edge_idx
by repeating the values for each target entry
'''
return self._upcast(self.edge_df['trgt'], df)

def upcast_face(self, df):
return self._upcast(self.e_face_idx, df)
''' Reindexes input data to self.edge_idx
by repeating the values for each face entry
'''
return self._upcast(self.edge_df['face'], df)

def upcast_cell(self, df):
return self._upcast(self.e_cell_idx, df)
''' Reindexes input data to self.edge_idx
by repeating the values for each cell entry
'''
return self._upcast(self.edge_df['cell'], df)

def _lvl_sum(self, df, lvl):
df_ = df.copy()
Expand Down Expand Up @@ -425,53 +427,33 @@ def _get_verts_pos(face):
polys = self.edge_df.groupby('face').apply(_get_verts_pos).dropna()
return polys

def _build_face_face_indexes(self): #pragma: no cover
#- BC -#
## this method raises a ValueError
## 'too many values to unpack'.
## It's not used anywhere in the code,
## or in the examples. I'm withdrawing
## it from coverage for now.
'''
This is hackish and not optimized,
should be provided by CGAL
'''
cc_idx = []
for srce0, trgt0, face0 in self.edge_idx:
for srce1, trgt1, face1 in self.edge_idx:
if face0 != face1 and trgt0 == srce1 and \
trgt1 == srce0 and not (face1, face0) in cc_idx:
cc_idx.append((face0, face1))
cc_idx = pd.MultiIndex.from_tuples(cc_idx, names=['facea', 'faceb'])
return cc_idx

def get_extra_indices(self):
"""Computes extra indices:
- `sheet.free_edges`: half-edges at the epithelium boundary
- `sheet.dble_edges`: half-edges inside the epithelium,
- `self.free_edges`: half-edges at the epithelium boundary
- `self.dble_edges`: half-edges inside the epithelium,
with an opposite
- `sheet.east_edges`: half of the `dble_edges`, pointing east
- `self.east_edges`: half of the `dble_edges`, pointing east
(figuratively)
- `sheet.west_edges`: half of the `dble_edges`, pointing west
- `self.west_edges`: half of the `dble_edges`, pointing west
(the order of the east and west edges is conserved, so that
the ith west half-edge is the opposite of the ith east half-edge)
- `sheet.sgle_edges`: joint index over free and east edges, spanning
- `self.sgle_edges`: joint index over free and east edges, spanning
the entire graph without double edges
- `sheet.wrpd_edges`: joint index over free edges followed by the
- `self.wrpd_edges`: joint index over free edges followed by the
east edges twice, such that a vector over the whole half-edge
dataframe is wrapped over the single edges
- `sheet.srtd_edges`: index over the whole half-edge sorted such that
- `self.srtd_edges`: index over the whole half-edge sorted such that
the free edges come first, then the east, then the west
Also computes:
- `sheet.Ni`: the number of inside full edges
(i.e. `len(sheet.east_edges)`)
- `sheet.No`: the number of outside full edges
(i.e. `len(sheet.free_edges)`)
- `sheet.Nd`: the number of double half edges
(i.e. `len(sheet.dble_edges)`)
- `sheet.anti_sym`: `pd.Series` with shape `(sheet.Ne,)`
- `self.Ni`: the number of inside full edges
(i.e. `len(self.east_edges)`)
- `self.No`: the number of outside full edges
(i.e. `len(self.free_edges)`)
- `self.Nd`: the number of double half edges
(i.e. `len(self.dble_edges)`)
- `self.anti_sym`: `pd.Series` with shape `(self.Ne,)`
with 1 at the free and east half-edges and -1
at the opposite half-edges.
Expand All @@ -490,7 +472,7 @@ def get_extra_indices(self):
we'll just assert it worked.
"""

if not 'opposite' in self.edge_df.columns:
if 'opposite' not in self.edge_df.columns:
self.edge_df['opposite'] = get_opposite(self.edge_df)

self.dble_edges = self.edge_df[self.edge_df['opposite'] >= 0].index
Expand Down
5 changes: 4 additions & 1 deletion tyssue/draw/plt_draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ def quick_edge_draw(sheet, coords=['x', 'y'], ax=None, **draw_spec_kw):

if ax is None:
fig, ax = plt.subplots()
else:
fig = ax.get_figure()

x, y = coords
srce_x = sheet.upcast_srce(sheet.vert_df[x]).values
Expand All @@ -157,7 +159,8 @@ def quick_edge_draw(sheet, coords=['x', 'y'], ax=None, **draw_spec_kw):
lines_x = np.insert(lines_x, slice(None, None, 2), np.nan)
lines_y = np.insert(lines_y, slice(None, None, 2), np.nan)
ax.plot(lines_x, lines_y, **draw_spec_kw)
return ax
ax.set_aspect('equal')
return fig, ax


def plot_forces(sheet, geom, model,
Expand Down
5 changes: 2 additions & 3 deletions tyssue/geometry/sheet_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ def update_normals(sheet):
coords = sheet.coords
face_pos = sheet.upcast_face(sheet.face_df[coords]).values
srce_pos = sheet.upcast_srce(sheet.vert_df[coords]).values
trgt_pos = sheet.upcast_trgt(sheet.vert_df[coords]).values

normals = np.cross(srce_pos - face_pos, trgt_pos - srce_pos)
normals = np.cross(srce_pos - face_pos,
sheet.edge_df[sheet.dcoords].values)
sheet.edge_df[sheet.ncoords] = normals

@staticmethod
Expand Down
31 changes: 31 additions & 0 deletions tyssue/io/csv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import pandas as pd
import numpy as np


def write_storm_csv(filename, points,
coords=['x', 'y', 'z'],
split_by=None, **csv_args):
"""
Saves a point cloud array in the storm format
"""
columns = ['frame', 'x [nm]', 'y [nm]', 'z [nm]',
'uncertainty_xy', 'uncertainty_z']
points = points.dropna()
storm_points = pd.DataFrame(np.zeros((points.shape[0], 6)),
columns=columns)
storm_points[['x [nm]', 'y [nm]', 'z [nm]']] = points[coords].values
storm_points['frame'] = 1
storm_points[['uncertainty_xy',
'uncertainty_z']] = 2.1
# tab separated values are faster and more portable than excel
if split_by is None:
if not filename.endswith('.csv'):
filename = filename+'.csv'
storm_points.to_csv(filename, **csv_args)
elif split_by in points.columns():
storm_points[split_by] = points[split_by]
# separated files by the column split_by
storm_points.groupby(split_by).apply(
lambda df:df.to_csv('{}_{}.csv'.format(
filename, df[split_by].iloc[0]),
**csv_args))
Empty file added tyssue/particles/__init__.py
Empty file.
Loading

0 comments on commit 60d0470

Please sign in to comment.