Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
19343bd
before sfn 2024
cudmore Oct 4, 2024
0f3faf7
before sfn 2024
cudmore Oct 4, 2024
51a3894
push on 20241017
cudmore Oct 18, 2024
5848192
push on 20241017
cudmore Oct 18, 2024
a159389
lots of work on colin kym
cudmore May 28, 2025
a5b1314
lots of work on colin kym
cudmore May 28, 2025
8ca7296
lots of work on colin kym
cudmore May 28, 2025
d5cdafe
lots of work on colin kym
cudmore May 28, 2025
8d4ca90
after hayfork trip
cudmore Jun 9, 2025
aac7b70
after hayfork trip
cudmore Jun 9, 2025
c3bafa7
lots
cudmore Jun 13, 2025
37fd59c
Refactor and add robust tests for colin_global and colin_stats: added…
cudmore Jun 20, 2025
a0b9d3a
Add colin development log to track ongoing changes and context
cudmore Jun 20, 2025
dd84e55
before colin tree changes
cudmore Jun 21, 2025
da5eba5
before scatter plot splitter (cursor)
cudmore Jun 23, 2025
b9f96d9
before scatter plot splitter (cursor)
cudmore Jun 23, 2025
b0221c3
before scatter plot splitter (cursor)
cudmore Jun 23, 2025
0647ddf
Add comprehensive logging system and file sorting to TIF backend
cudmore Jun 26, 2025
ff7bc0f
tif file backend and tif table widget
cudmore Jun 28, 2025
1577d10
tif file backend and tif table widget
cudmore Jun 28, 2025
a68808f
tif file backend and tif table widget
cudmore Jun 28, 2025
d25e63d
tif file backend and tif table widget
cudmore Jun 28, 2025
4093838
tif file backend and tif table widget
cudmore Jun 28, 2025
678923b
tif file backend and tif table widget
cudmore Jun 28, 2025
9308475
tif file backend and tif table widget
cudmore Jun 28, 2025
8519f64
tif file backend and tif table widget
cudmore Jun 28, 2025
29a076f
tif file backend and tif table widget
cudmore Jun 28, 2025
2a589b9
tif file backend and tif table widget
cudmore Jun 28, 2025
05258b0
tif file backend and tif table widget
cudmore Jun 28, 2025
df48866
Fix MainWindow import in tif_pool_scatter.py
cudmore Jul 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
*.egg-info
.coverage*
.vscode/
data/
pyinstaller/macos/_secrets.py
sandbox/

pyinstaller/monterey/tmp_env

build/
Expand All @@ -8,6 +15,10 @@ sanpy_env/*
sanpy.log
sanpy/sanpy.log

# Log files
logs/
*.log

.AppleDouble
.DS_Store
*.pyc
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@

SanPy Documentation is available at [https://cudmore.github.io/SanPy/](https://cudmore.github.io/SanPy/)

## 202403

### New features

- Re-added the File - Save menu. This will save the current analysis for one file or a folder.
- Added a "bin time" pooling option to summary plugin. Makes a table with stats (count, mean, std, se, median) in evenly spaced windows of time. For example pooles between [0,2) then [2,4) then [4,6), etc, seconds.
- Added a colorbar to scatter plot plugin when selecting hue as "Time". This allows users to know where a point in the scatter occured in the recording time.

### Bug fixes

- Fixed bug in plugin - summarize results - sweep summary
- Fixed bug in plugin - plot scatter when selecting hue of Time or Sweep

## 20240126

- Added a file folder opening window. This is show at first run and allows users to open new and previous opened files and folder.
Expand Down
36 changes: 36 additions & 0 deletions dev-notes/colin-dev-log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Colin Development Log

This file tracks ongoing development, refactoring, and testing for colin-related code in the SanPy project.

**Note:** This development log was mostly auto-generated by Cursor AI, an AI coding assistant, to help track changes and maintain context during development.

---

## 2024-06-13: Refactor, Utility Improvements, and Robust Testing

### Major Changes
- **Refactored** `colin_global.py` and `colin_stats.py` for clarity, maintainability, and best practices.
- **Introduced** the `FileInfo` dataclass for robust parsing of file paths (e.g., extracting cellID, epoch, date, region, condition).
- **Added** a utility iterator function to return unique rows for a given cellID from a DataFrame.
- **Replaced** ad-hoc file parsing logic in `colin_stats.py` with the new `FileInfo` dataclass.
- **Fixed** pandas `SettingWithCopyWarning` by using `.copy()` when needed.

### Testing
- **Created** `sanpy/kym/tests/test_colin_global.py` and `test_colin_stats.py`:
- Each test prints results and uses `assert` statements to verify expected values.
- Tests cover normal cases, edge cases, and error conditions.
- Tests for DataFrame operations, iterator logic, and `.copy()` best practices.
- **Added** `run_all_tests.py` to run all colin-related tests and provide a summary.
- **Added** a `README.md` in the tests folder to document test structure and usage.

### Benefits
- **Regression-proof**: Tests will catch breaking changes or regressions.
- **Documentation**: Test cases and this log serve as living documentation.
- **Maintainability**: Refactored code is easier to extend and debug.
- **Professional structure**: Follows best practices for code and test organization.

---

**Next Steps:**
- Continue to log all major refactors, new utilities, and test improvements here.
- Use this file for context when returning to the project or onboarding collaborators.
10 changes: 9 additions & 1 deletion pyinstaller/macos/build_arm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,14 @@ conda install -y numpy \
conda install -y -c conda-forge mplcursors

pip install pyabf

# 20250627, abb building sanpykym, we might need, pyqtdarktheme-fork
pip install pyqtdarktheme
pip install qtawesome
pip install roifile
pip install statannotations
# pip install tifffile
# pip install tables

# install sanpy with no packages
pip install -e '../../.'
Expand All @@ -76,4 +83,5 @@ pip install pyinstaller
# build the app with pyinstaller
python macos_build.py

python notarizeSanpy.py dist_arm
# abb 202506 turn back on to notarize, getting password error
# python notarizeSanpy.py dist_arm
2 changes: 2 additions & 0 deletions pyinstaller/macos/readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
This folder contains scripts to build macOS app(s) from Python source code using pyinstaller.

My apple developer account is at https://developer.apple.com/account

Building a Python app on macOS is by no means simple. The app needs to be properly codesigned, notarized on an Apple server (requires uploading a zip of the app to Apple), waiting for the ok, and then staple(ing) the app with the notarization.

This all requires an Apple Developer Subscription which is $99/year.
Expand Down
67 changes: 64 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,67 @@
requires = ["setuptools>=45", "setuptools_scm[toml]>=6.2", "wheel"]
build-backend = "setuptools.build_meta"

#[project]
[project]
name = "sanpy"
# version = "0.0.1" # Remove any existing version parameter.
#dynamic = ["version"]
dynamic = ["version"]
requires-python = ">=3.11"
dependencies = [] # Base install has no requirements

[project.optional-dependencies]
gui = [
"h5py",
"matplotlib",
"mplcursors",
"numpy>=1.20.0",
"pandas>=2.0.0",
"pyabf",
"PyQt5>=5.15.0",
"pyqtdarktheme-fork",
"pyqtgraph",
"qtawesome",
"qtpy",
"requests",
"roifile", # For reading Fiji ROI files
"scikit-image",
"scipy>=1.8.0",
"seaborn", # For statistical visualizations
"statannotations", # For statistical annotations
"tables",
"tifffile"
]

dev = [
"flake8",
"ipython",
"jupyter",
"mkdocs",
"mkdocs-material",
"mkdocs-jupyter",
"mkdocstrings",
"mkdocstrings-python",
"pyinstaller",
"pytest",
"pytest-cov",
"pytest-qt",
"tornado",
"tox"
]

test = [
"flake8",
"pytest",
"pytest-cov",
"pytest-qt",
"tox"
]

[project.scripts]
sanpy = "sanpy.interface.sanpy_app:main"
sanpykym = "sanpy.kym.interface.kym_file_list.tif_tree_window:main"

[tool.setuptools]
packages = ["sanpy"]

[tool.setuptools_scm]
write_to = "sanpy/_version.py"
Expand All @@ -15,4 +73,7 @@ local_scheme = "no-local-version"
[tool.ruff]
ignore = [
"E501", # Supress line-too-long warnings: trust black's judgement on this one.
]
]

[tool.pytest.ini_options]
addopts = "--ignore=napari"
26 changes: 26 additions & 0 deletions readme-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,32 @@ git tag -d v0.1.25
git push --delete origin v0.1.25
```

202402

list remote tags
git ls-remote --tags origin
commit with a tag
git tag -a v1.0.36 -m 'release 1.0.36'
push the tag
git push --follow-tags

get version from setup
python setup.py --version

I AM SO SICK OF VERSIONING !!!!!!

Logic is (this is the way)

```
update version in setup.py
update version in _myVersion.py
git commit -am 'v1.0.42'
git push

git tag -a v1.0.42 -m 'release v1.0.42'
git push --follow-tags
```

## Lock down a version to accompany SanPy manuscript

Working on publishing v0.1.8
Expand Down
4 changes: 2 additions & 2 deletions sanpy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# using this to turn off for 1st sanpy publication
D_BJ_MANUSCRIPT = True
DO_KYMOGRAPH_ANALYSIS = False
D_BJ_MANUSCRIPT = False
DO_KYMOGRAPH_ANALYSIS = True

from .sanpyLogger import *

Expand Down
37 changes: 32 additions & 5 deletions sanpy/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,26 @@ def _loadLineScanHeader(path):

txtFile = os.path.splitext(path)[0] + ".txt"

if not os.path.isfile(txtFile):
# find "ISAN Linescan 6 Metadata.txt"
logger.info(f'did not find {txtFile}')
logger.info(' -->> searching ...')

_folder, _file = os.path.split(path)
_file, _ = os.path.splitext(_file)
_file += ' Metadata.txt'
logger.info(f' -->> looking for Olympus "{_file}"')
txtFile = os.path.join(_folder, _file)
if not os.path.isfile(txtFile):
_folder, _file = os.path.split(path)
_file, _ = os.path.splitext(_file)
_file = _file.split('_')[0] # may fail
_file += '.txt'
logger.info(f' -->> looking for Olympus "{_file}"')
txtFile = os.path.join(_folder, _file)
if not os.path.isfile(txtFile):
logger.warning(f'DID NOT FIND CORRESPONDING OLYMPUS FILE: {os.path.split(path)[1]}')

if not os.path.isfile(txtFile):
# logger.error(f"did not find file:{txtFile}")

Expand Down Expand Up @@ -283,6 +303,17 @@ def _loadLineScanHeader(path):
# elif line.startswith('"Image Size(Unit Converted)"'):
# print('loadLineScanHeader:', line)

elif line.startswith('"Date"'):
# "Date" "09/12/2024 01:33:26.239 PM"
# logger.info(f'date line is: {line}')
_date, _datetime = line.split('\t')
_datetime = _datetime.replace('"', '') # remove ""
_date, _time, _ampm = _datetime.split(' ')
# logger.info(f' _date:{_date} _time:{_time} _ampm:{_ampm}')

theRet ['date'] = _date
theRet ['time'] = _time + ' ' + _ampm

# tif shape is (lines, pixels)
if gotNumPixels and gotImageSize:
shape = (theRet["numLines"], theRet["numPixels"])
Expand Down Expand Up @@ -341,9 +372,5 @@ def getFileList(path, depth=1):
return fileList

if __name__ == '__main__':
path = '/Users/cudmore/Dropbox/data/cell-shortening/fig1'
fileList = getFileList(path, 4)
for file in fileList:
print(file)

pass

Loading
Loading