Skip to content

Commit

Permalink
Merge branch '9984c47'
Browse files Browse the repository at this point in the history
  • Loading branch information
vincenzooo committed Nov 22, 2024
2 parents d22dc4c + 306b307 commit b851cdb
Show file tree
Hide file tree
Showing 17 changed files with 1,519 additions and 505 deletions.
9 changes: 5 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ You can get the most updated version by cloning the source code from github and

To do this:

1. use the ``Code`` button at top of page, or clone from command-lineç
``git clone https://github.com/vincenzooo/pyXSurf.git``.
1. use the ``Code`` button at top of page, or clone from command-line: ``git clone https://github.com/vincenzooo/pyXSurf.git``.

2. move to the folder with the code and call from command line ``pip install .`` (equivalent to ``python setup.py install``).
This will perform a "regular" installation (meaning that the code is copied to ``site-packages`` folders, which holds all installed Python libraries, and made accessible to your system).
Expand All @@ -44,7 +43,7 @@ If instead you plan to modify pyXsurf code, or want a non-permanente installatio
Uninstalling
------------

Code can be uninstalled calling ``pip uninstall pyXsurf`` from a command prompt, or from source code folder calling directly the setup file ``python setup.py develop -u`` (if you installed as developer, deinstallation is expected to work only with most recent pip versions, at least >=19.1.1, otherwise it should be enough to delete the folder).
Code can be uninstalled calling ``pip uninstall pyXsurf`` from a command prompt. N.B.: previous version can also be uninstalled from source code folder calling directly the setup file ``python setup.py develop -u``, this is no more advised (if you installed as developer, deinstallation is expected to work only with most recent pip versions, at least >=19.1.1, otherwise it should be enough to delete the folder).

How to use
==========
Expand All @@ -54,7 +53,9 @@ works without errors, you can now import and use the different modules (see desc

.. code:: python
from pySurf.data2D import data2D
from pySurf.data2D_class import Data2D
or try the library in a Jupyter notebook, you can start from the example `pySurf_demo.ipynb`, in the install folder.

In addition to the `official documentation <https://pyxsurf.readthedocs.io>`_ , you can find examples and data in a ``test`` subfolder of each
module and at the end of module files. Functions are usually documented with docstrings (but these might be in the wrong place, please be patient and look well in the code).
Expand Down
872 changes: 872 additions & 0 deletions docs/source/notebooks/pySurf_demo_beatrix.ipynb

Large diffs are not rendered by default.

841 changes: 423 additions & 418 deletions pySurf_demo.ipynb

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions source/dataIO/arrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,25 @@ def vectorize(arg, n, force_if_n=False):
"""

# <<<<<<< HEAD
if (real_len(arg) != n) or force_if_n:
try:
arg=[arg.deepcopy() for _ in range(n)]
except AttributeError: #fails e.g. if tuple which don't have copy method
arg=[arg for _ in range(n)]
# =======
# #FIXME: this is still not a reliable mechanism, see extended tests below.
# # in other cases used len(np.shape), maybe works better, e.g.:
# # if len(np.shape(reader)) == 0: #vectorize #np.size(reader) == 1:
# # reader=[reader]*len(rfiles)

# if args:
# for a in args:
# if (np.size(a) == 1):
# args=[[] for i in range(n)]
# elif (len(a) != n):
# args=[args for i in range(n)]
# >>>>>>> 9984c47
else:
if (n == 1) and len(np.shape(arg)) == 0:
arg = [arg]
Expand All @@ -272,12 +286,50 @@ def test_vectorize():

assert vectorize([1,2,3], 2) == [[1,2,3],[1,2,3]]
assert vectorize([], 3) == [[],[],[]]

# <<<<<<< HEAD
assert vectorize([1,2,3], 3, True) == [[1,2,3],[1,2,3],[1,2,3]]

assert vectorize([[1,2],[3,4]],2) == [[1,2],[3,4]]
assert vectorize([[1,2],[3,4]],2,True) == [[[1,2],[3,4]],[[1,2],[3,4]]]

print('All tests passed.')
# =======
assert vectorize([1,2,3], 3) == [[1,2,3],[1,2,3],[1,2,3]]

#extended test
a = []
b = 5
c = [3]

print("(a,3) --> ",vectorize(a,3))
print("(a,1) --> ",vectorize(a,1))
print("(b,3) --> ",vectorize(b,3))
print("(b,1) --> ",vectorize(b,1))
print("(c,3) --> ",vectorize(c,3))
print("(c,1) --> ",vectorize(c,1))

b = 'cane'
c = ['cane']

print("(b,3) --> ",vectorize(b,3))
print("(b,1) --> ",vectorize(b,1))
print("(c,3) --> ",vectorize(c,3))
print("(c,1) --> ",vectorize(c,1))
# >>>>>>> 9984c47


def inspect_vector(obj):
"""Print a set of dimensional information about the object.
The returned information should be useful to discriminate between different lengths, dimensions and rank.
"""

print("len: ",len(obj))
print("np.size: ",np.size(obj))
print("np.shape: ",np.shape(obj))
print("len of shape: ",len(np.shape(obj)))

def make_raster(*vectors, as_axis = False, extend = True):
"""Create a raster grid on the base of a list of vectors.
Expand Down
48 changes: 36 additions & 12 deletions source/dataIO/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@
import warnings
warnings.filterwarnings("error", category=np.VisibleDeprecationWarning)

def files_with_ext(base_folder, folder_glob_pattern= "", file_extension=".*"):
"""
Find files with a given extension within folders matching a glob pattern.
:param base_folder: The base directory to start the search from.
:param folder_glob_pattern: The glob pattern to match folders.
:param file_extension: The extension of the files to find. Pass empty string for folders or files with no extension.
:return: A list of paths to files matching the given extension in folders matching the glob pattern.
"""
from pathlib import Path

# Define the base path to start searching from
base_path = Path(base_folder)

# Initialize a list to hold the matched file paths
matched_files = []

# Find all folders matching the glob pattern
for folder in base_path.glob(folder_glob_pattern):
if folder.is_dir(): # Ensure the matched path is a directory
# Use rglob to find all files with the given extension in the current folder and its subfolders
matched_files.extend(str(f) for f in folder.rglob(f'*{file_extension}'))

return matched_files

def read_blocks(filename,delimiter = '\n\n', comment = None,*args,**kwargs):
"""Read a file containing blocks of numerical data separated by a white line.
Expand Down Expand Up @@ -37,20 +62,19 @@ def read_blocks(filename,delimiter = '\n\n', comment = None,*args,**kwargs):

return pList


def print_results(a, title):
'''pass result and descriptive title for a test.'''

print('\n====== ',title, ' ======\n')
print('%i blocks read'%len(a))
print('block shapes: ',[aa.shape for aa in a])
print('block contents: ')
for i,aa in enumerate(a):
print('block #%i:\n'%(i+1),'[%s\n..\n..\n%s]\n'%(','.join(map(str,aa[:3])),','.join(map(str,aa[-2:]))))
return a

def test_read_blocks(filename=None):

def print_results(a, title):
'''pass result and descriptive title for a test.'''

print('\n====== ',title, ' ======\n')
print('%i blocks read'%len(a))
print('block shapes: ',[aa.shape for aa in a])
print('block contents: ')
for i,aa in enumerate(a):
print('block #%i:\n'%(i+1),'[%s\n..\n..\n%s]\n'%(','.join(map(str,aa[:3])),','.join(map(str,aa[-2:]))))
return a

#infolder = r'C:\Users\kovor\Documents\python\pyXTel\source\pyProfile\test\input_data\'

infolder = r'C:\Users\kovor\Documents\python\pyXTel\source\dataIO\test\test_data\blocks'
Expand Down
2 changes: 1 addition & 1 deletion source/dataIO/roi.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


# 2020/10/25 functions were here, not sure why, moved in pySurf.roi
# 2020/10/25 functions were here, not sure why, moved to pySurf.roi

19 changes: 15 additions & 4 deletions source/plotting/plot_positions.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,29 @@ def plot_poly(v,ls='',ms=''):
#plot lines
return plt.plot(mh[:,0],mh[:,1],ls)[0]
'''


import numpy as np

def plot_poly(v,*args,**kwargs):
"""plot a polygon defined by a list of vertices `v` as coordinate couples.
Just a thin wrapper around `plt.plot`, it just accepts points in transpose form and adds a copy of first point at the."""
Just a thin wrapper around `plt.plot`, it just accepts points in transpose form and adds a copy of first point at the end.
Accept all matplotlib keywords, e.g.;
hatch = '/',
facecolor = 'none'
edgecolor = 'black'
for line-filled black shape. The default is a filled shape with matplotlib next color (TODO: change it to empty shape with matplotlib color for lines). The three parameters in the example probabily need all to be set for hatched shapes.
"""

v=np.array(v)
# duplicate first point at the end:
v=np.vstack([v,v[0,:]])
# plt.plot return a list of one element

#plot lines
return plt.plot(*v.T,*args,**kwargs)
# plot lines
return plt.fill(*v.T,*args,**kwargs) # plt.plot(*v.T,*args,**kwargs)

def plot_rect(c1,c2,*args,**kwargs):
"""plot a polygon defined by a 2 element list with coordinates of opposite corners.
Expand Down
27 changes: 20 additions & 7 deletions source/pyProfile/profile_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,10 @@ def __init__(self,x=None,y=None,file=None,reader=None,
x=None
else:
if y is not None:
y=np.array(y) #onvert to array if not

#pdb.set_trace()
y=np.array(y) #convert to array if not
x=np.array(x)
# import pdb
# pdb.set_trace()
self.file=file #initialized to None if not provided
if file is not None:
assert y is None
Expand Down Expand Up @@ -306,9 +307,10 @@ def __init__(self,x=None,y=None,file=None,reader=None,
x=np.arange(np.size(y))

#if data is not None:
self.x, self.y = x, y
# self.x, self.y = np.array(x), np.array(y)

self.x,self.y=register_profile(self.x,self.y,scale=scale,*args,**kwargs) # se load_profile calls register, this
breakpoint()
self.x,self.y=register_profile(np.array(x), np.array(y),scale=scale,*args,**kwargs) # se load_profile calls register, this
#goes indented.

if np.size(units) == 1:
Expand Down Expand Up @@ -567,7 +569,7 @@ def __rtruediv__(self,other):

res = self.copy()
if np.size(other) == 1:
if isinstance(other,self): # scalar
if isinstance(other,self.__class__): # scalar
sel = (self.y != 0)
res = self.copy()
res.y[sel] = other*(1./self.y[sel])
Expand Down Expand Up @@ -637,7 +639,7 @@ def merge(self,other,*args,**kwargs):
if isinstance(other,self.__class__):
#res = merge_profiles([[self.x,self.y],[other.x,other.y]],*args,**kwargs)
res = merge_profile(self.x,self.y,other.x,other.y,*args,**kwargs)
res = Profile(*res,units=self.units,name=self.name + " // " + other.name)
res = self.__class__(*res,units=self.units,name=self.name + " // " + other.name)
else:
raise ValueError("Unrecognized type in merge")
return res
Expand Down Expand Up @@ -1040,6 +1042,17 @@ def __init__(self, *args, **kwargs):
""" N.B.: TODO: could use linecollections for plotting https://matplotlib.org/stable/api/collections_api.html#matplotlib.collections.LineCollection
"""

def merge(self, mode='raw',*args,**kwargs):
res = self[0]
for p in self[1:]:
res = res.merge(p,*args,**kwargs)
return res

def save(self,file, type= 'vstack', *args,**kwargs):
"""save stacked or on separate files"""
pp = self.merge()
pp.save(file, *args,**kwargs)

def test_load_plist(rfiles = None):

if rfiles is None:
Expand Down
6 changes: 3 additions & 3 deletions source/pySurf/data2D.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ def _validate_degree(degree, axis):
raise ValueError("Degree must be scalar when leveling by line (axis != None): received {}".format(degree))
return degree

def _level_by_line(data, degree, *args, **kwargs):
def _level_by_line(data, y, degree, *args, **kwargs):
leg = fitlegendre(y, data, degree, *args, **kwargs)
return leg

Expand All @@ -258,9 +258,9 @@ def _level_plane(data, degree, *args, **kwargs):
degree = _validate_degree(degree, axis)

if axis == 0:
leg = _level_by_line(data, degree, *args, **kwargs)
leg = _level_by_line(data, y, degree, *args, **kwargs)
elif axis == 1:
leg = _level_by_line(data.T, degree, *args, **kwargs).T
leg = _level_by_line(data.T, x, degree, *args, **kwargs).T
elif axis is None:
leg = _level_plane(data, degree, *args, **kwargs)
else:
Expand Down
34 changes: 31 additions & 3 deletions source/pySurf/data2D_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,10 @@ def rotate(self, angle, *args, **kwargs):
"""call data2D.rotate_data, which rotate array of an arbitrary angle in degrees in direction
(from first to second axis)."""
res = self.copy()
# FIXME: rotation doesn't work without conversion to points.
usepoints = kwargs.pop("usepoints",True)
res.data, res.x, res.y = rotate_data(
self.data, self.x, self.y, angle, *args, **kwargs
self.data, self.x, self.y, angle, usepoints=usepoints, *args, **kwargs
)
return res

Expand Down Expand Up @@ -530,7 +532,7 @@ def apply_to_data(self, func, *args, **kwargs):
def crop(self, *args, **kwargs):
"""crop data making use of function data2D.crop_data, where data,x,y are taken from a"""
res = self.copy()
res.data, res.x, res.y = crop_data(self.data, self.x, self.y, *args, **kwargs)
res.data, res.x, res.y = crop_data(res.data, res.x, res.y, *args, **kwargs)
return res

crop = update_docstring(crop, crop_data)
Expand Down Expand Up @@ -561,6 +563,32 @@ def resample(self, other, *args, **kwargs):

resample = update_docstring(resample, resample_data)

def divide_and_crop(self, n, m):
"""Divide data in n x m equal size data. Data, returned as Dlsit, are ordered as coordinates."""

xmin,xmax = span(self.x)
ymin,ymax = span(self.y)

# Width and height of each sub-rectangle
x_step = (xmax - xmin) / n
y_step = (ymax - ymin) / m

dl = []
# Nested loops to iterate over each sub-rectangle
for j in range(m):
for i in range(n):
# Calculating the bounds for this sub-rectangle
x_start = xmin + i * x_step
x_end = xmin + (i + 1) * x_step
y_start = ymax - (j + 1) * y_step
y_end = ymax - j * y_step
dd = self.crop((x_start, x_end), (y_start, y_end))
dd.name = fn_add_subfix(dd.name, ' (%i,%i)'%(i,j))
# Call the crop function with the calculated bounds
dl.append(dd)

return Dlist(dl)

def add_markers(self, *args, **kwargs):
#f = plt.figure()
self.plot()
Expand Down Expand Up @@ -805,7 +833,7 @@ def plot(self,linear = False,*args, **kwargs):


def avgpsd(self, *args, **kwargs):
"""avg, returns f and p. Can use data2D.projection keywords `span` and `expand` to return PSD ranges."""
"""avg, returns a PSD (linear) object. Can use data2D.projection keywords `span` and `expand` to return PSD ranges."""

#return Profile(self.y, projection(self.data, axis=1, *args, **kwargs), units = [self.units[1], self.units[2]])
res = super().projection(axis = 1, *args, **kwargs)
Expand Down
10 changes: 6 additions & 4 deletions source/pySurf/points.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,11 @@ def points_find_hull(pts):
plt.plot(hull[:,0], hull[:,1], 'r--', lw=2)."""

from scipy.spatial import ConvexHull
if pts.shape[1] == 2:

pts = np.array(pts)
if np.shape(pts)[1] == 2:
xypts = pts
elif pts.shape[1] == 3:
elif np.shape(pts)[1] == 3:
xypts=pts[~np.isnan(pts[:,2]),:2]
else:
raise ValueError("wrong shape for points in points_find_hull")
Expand Down Expand Up @@ -389,7 +391,7 @@ def matrix_to_points(data,xgrid,ygrid,transpose=False):
return np.vstack([x.flatten(),y.flatten(),data.T.flatten()]).T


def get_points(filename,x=None,y=None,xrange=None,yrange=None,matrix=False,addaxis=False,scale=None,center=None,skip_header=None,delimiter=','):
def get_points(filename,x=None,y=None,xrange=None,yrange=None,matrix=False,addaxis=False,scale=None,center=None,skip_header=None,delimiter=',',*args,**kwargs):
"""
Return a set of xyz points (N,3) from generic csv files in xyz or matrix format.
Expand Down Expand Up @@ -448,7 +450,7 @@ def get_points(filename,x=None,y=None,xrange=None,yrange=None,matrix=False,addax
else:
skip=skip_header

mdata=np.genfromtxt(filename,skip_header=skip,delimiter=delimiter)
mdata=np.genfromtxt(filename,skip_header=skip,delimiter=delimiter,*args,**kwargs)
if (matrix):
if addaxis == True: addaxis = 'xy'

Expand Down
Loading

0 comments on commit b851cdb

Please sign in to comment.