ZaksPhysicsLibrary 1.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PhysicsLibrary/__init__.py +59 -0
- PhysicsLibrary/analysis.py +251 -0
- PhysicsLibrary/dataset.py +125 -0
- PhysicsLibrary/file_parser.py +59 -0
- PhysicsLibrary/file_parser_generic.py +287 -0
- PhysicsLibrary/loaders/__init__.py +0 -0
- PhysicsLibrary/loaders/oxysoft_loader.py +235 -0
- PhysicsLibrary/loaders/pt2_loader.py +43 -0
- PhysicsLibrary/loaders/tdt_loader.py +49 -0
- PhysicsLibrary/models.py +62 -0
- PhysicsLibrary/processing_TDT.py +273 -0
- zaksphysicslibrary-1.2.2.dist-info/METADATA +142 -0
- zaksphysicslibrary-1.2.2.dist-info/RECORD +16 -0
- zaksphysicslibrary-1.2.2.dist-info/WHEEL +5 -0
- zaksphysicslibrary-1.2.2.dist-info/licenses/LICENSE +21 -0
- zaksphysicslibrary-1.2.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""
|
|
2
|
+
processing_TDT.py
|
|
3
|
+
-----------------
|
|
4
|
+
Signal processing pipeline for TDT (Tucker-Davis Technologies) fibre photometry data.
|
|
5
|
+
|
|
6
|
+
Handles loading, bleaching correction, denoising, and event marker extraction.
|
|
7
|
+
Depends on the `tdt` Python SDK for reading tank files.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
from scipy.optimize import curve_fit
|
|
14
|
+
from scipy.signal import butter, filtfilt
|
|
15
|
+
import tdt
|
|
16
|
+
|
|
17
|
+
from .models import double_exponential_model as double_exponential
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def validate_tdt_folder(path):
|
|
21
|
+
"""
|
|
22
|
+
Validate whether a directory contains a TDT recording block.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
path : str
|
|
27
|
+
Path to the TDT data folder.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
tuple
|
|
32
|
+
(bool, str)
|
|
33
|
+
- True + folder name if valid
|
|
34
|
+
- False + error message if invalid
|
|
35
|
+
"""
|
|
36
|
+
if not path:
|
|
37
|
+
return False, "No folder selected."
|
|
38
|
+
|
|
39
|
+
has_tbk = any(fname.endswith('.Tbk') for fname in os.listdir(path))
|
|
40
|
+
|
|
41
|
+
if has_tbk:
|
|
42
|
+
return True, os.path.basename(path)
|
|
43
|
+
else:
|
|
44
|
+
return False, "Invalid Folder: No TDT block files (.Tbk) found."
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def process_tdt_folder(folder_path):
|
|
48
|
+
"""
|
|
49
|
+
Full photometry processing pipeline for a TDT recording.
|
|
50
|
+
|
|
51
|
+
Steps:
|
|
52
|
+
1. Load TDT block
|
|
53
|
+
2. Extract 465 nm (signal) and optional 415 nm (reference)
|
|
54
|
+
3. Perform regression-based motion correction
|
|
55
|
+
4. Correct photobleaching trend
|
|
56
|
+
5. Compute ΔF/F
|
|
57
|
+
6. Denoise signal
|
|
58
|
+
7. Extract event markers
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
folder_path : str
|
|
63
|
+
Path to TDT recording folder.
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
dict
|
|
68
|
+
Processed signals and metadata:
|
|
69
|
+
- x: time vector
|
|
70
|
+
- raw: corrected fluorescence signal
|
|
71
|
+
- corr: final ΔF/F (denoised)
|
|
72
|
+
- dff: same as corr (alias)
|
|
73
|
+
- f0: bleaching baseline
|
|
74
|
+
- fs: sampling frequency
|
|
75
|
+
- store: signal label
|
|
76
|
+
- markers: behavioral event markers
|
|
77
|
+
"""
|
|
78
|
+
data_struct = get_tdt_struct(folder_path)
|
|
79
|
+
streams = data_struct.streams.keys()
|
|
80
|
+
|
|
81
|
+
name_465 = next((s for s in streams if '465' in s), None)
|
|
82
|
+
name_415 = next((s for s in streams if '415' in s), None)
|
|
83
|
+
|
|
84
|
+
if not name_465:
|
|
85
|
+
raise ValueError("No 465 signal found")
|
|
86
|
+
|
|
87
|
+
x, y_465, fs = get_plot_data(data_struct, name_465)
|
|
88
|
+
|
|
89
|
+
if name_415:
|
|
90
|
+
_, y_415, _ = get_plot_data(data_struct, name_415)
|
|
91
|
+
p = np.polyfit(y_415, y_465, 1)
|
|
92
|
+
y_fit = np.polyval(p, y_415)
|
|
93
|
+
y_final = y_465 - y_fit
|
|
94
|
+
display_name = f"Corrected {name_465} (via {name_415})"
|
|
95
|
+
else:
|
|
96
|
+
y_final = y_465
|
|
97
|
+
display_name = f"{name_465} (Uncorrected)"
|
|
98
|
+
|
|
99
|
+
_, trend = correct_bleaching(y_final, fs)
|
|
100
|
+
|
|
101
|
+
f0 = np.maximum(trend, 1e-6)
|
|
102
|
+
dff = (y_final - f0) / f0
|
|
103
|
+
dff = denoise_signal(dff, fs, cutoff=5)
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
"x": x,
|
|
107
|
+
"raw": y_final,
|
|
108
|
+
"corr": dff,
|
|
109
|
+
"dff": dff,
|
|
110
|
+
"f0": f0,
|
|
111
|
+
"fs": fs,
|
|
112
|
+
"store": display_name,
|
|
113
|
+
"markers": get_event_markers(data_struct),
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def get_tdt_struct(path):
|
|
118
|
+
"""
|
|
119
|
+
Load a Tucker-Davis Technologies (TDT) recording block.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
path : str
|
|
124
|
+
Folder containing TDT data.
|
|
125
|
+
|
|
126
|
+
Returns
|
|
127
|
+
-------
|
|
128
|
+
object
|
|
129
|
+
Parsed TDT data structure.
|
|
130
|
+
"""
|
|
131
|
+
data = tdt.read_block(path)
|
|
132
|
+
if data is None:
|
|
133
|
+
raise Exception("TDT returned an empty object.")
|
|
134
|
+
return data
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def get_plot_data(data, store_name, channel=0, max_points=None):
|
|
138
|
+
"""
|
|
139
|
+
Extract time-series data from a TDT stream.
|
|
140
|
+
|
|
141
|
+
Parameters
|
|
142
|
+
----------
|
|
143
|
+
data : object
|
|
144
|
+
TDT data structure
|
|
145
|
+
store_name : str
|
|
146
|
+
Stream name (e.g., 'x465A')
|
|
147
|
+
channel : int
|
|
148
|
+
Channel index
|
|
149
|
+
max_points : int or None
|
|
150
|
+
Optional downsampling limit
|
|
151
|
+
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
tuple
|
|
155
|
+
(time array, signal array, sampling frequency)
|
|
156
|
+
"""
|
|
157
|
+
stream = data.streams[store_name]
|
|
158
|
+
fs = stream.fs
|
|
159
|
+
|
|
160
|
+
data_2d = np.atleast_2d(stream.data)
|
|
161
|
+
if channel >= data_2d.shape[0]:
|
|
162
|
+
channel = 0
|
|
163
|
+
|
|
164
|
+
y_full = data_2d[channel, :]
|
|
165
|
+
|
|
166
|
+
if max_points:
|
|
167
|
+
ds_factor = max(1, len(y_full) // max_points)
|
|
168
|
+
y = y_full[::ds_factor]
|
|
169
|
+
x = np.arange(len(y)) * (ds_factor / fs)
|
|
170
|
+
else:
|
|
171
|
+
y = y_full
|
|
172
|
+
x = np.arange(len(y)) / fs
|
|
173
|
+
|
|
174
|
+
return x, y, fs
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def correct_bleaching(y, fs):
|
|
178
|
+
"""
|
|
179
|
+
Estimate and correct photobleaching using masked curve fitting.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
corrected : array
|
|
184
|
+
Bleaching-corrected signal
|
|
185
|
+
trend : array
|
|
186
|
+
Estimated baseline trend
|
|
187
|
+
"""
|
|
188
|
+
x = np.arange(len(y)) / fs
|
|
189
|
+
|
|
190
|
+
threshold = np.median(y)
|
|
191
|
+
mask = y > threshold
|
|
192
|
+
x_fit, y_fit = x[mask], y[mask]
|
|
193
|
+
|
|
194
|
+
if len(y_fit) < 100:
|
|
195
|
+
return y, np.zeros_like(y)
|
|
196
|
+
|
|
197
|
+
k_guess = np.percentile(y_fit, 10)
|
|
198
|
+
total_amp = np.max(y_fit) - k_guess
|
|
199
|
+
p0 = [total_amp * 0.6, 0.05, total_amp * 0.4, 0.0001, k_guess]
|
|
200
|
+
lower = [0, 0, 0, 0, k_guess * 0.8]
|
|
201
|
+
upper = [np.inf, 1, np.inf, 0.1, np.max(y_fit)]
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
popt, _ = curve_fit(double_exponential, x_fit, y_fit, p0=p0,
|
|
205
|
+
bounds=(lower, upper), maxfev=10000)
|
|
206
|
+
trend = double_exponential(x, *popt)
|
|
207
|
+
except Exception:
|
|
208
|
+
# curve_fit failed — fall back to log-linear fit as a rough trend estimate
|
|
209
|
+
import warnings
|
|
210
|
+
warnings.warn(
|
|
211
|
+
"correct_bleaching: double-exponential fit failed; falling back to log-linear trend.",
|
|
212
|
+
RuntimeWarning, stacklevel=2,
|
|
213
|
+
)
|
|
214
|
+
coeffs = np.polyfit(x_fit, np.log(np.maximum(y_fit, 1e-6)), 1)
|
|
215
|
+
trend = np.exp(np.polyval(coeffs, x))
|
|
216
|
+
|
|
217
|
+
corrected = y - trend + trend[0]
|
|
218
|
+
return corrected, trend
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def get_event_markers(data):
|
|
222
|
+
"""
|
|
223
|
+
Extract behavioral event markers from TDT epoc data.
|
|
224
|
+
|
|
225
|
+
Returns
|
|
226
|
+
-------
|
|
227
|
+
list of dict
|
|
228
|
+
Each dict contains:
|
|
229
|
+
- time
|
|
230
|
+
- label
|
|
231
|
+
- color
|
|
232
|
+
"""
|
|
233
|
+
if not hasattr(data.epocs, 'Note'):
|
|
234
|
+
return []
|
|
235
|
+
|
|
236
|
+
notes = data.epocs.Note.notes
|
|
237
|
+
onsets = data.epocs.Note.onset
|
|
238
|
+
|
|
239
|
+
# Experiment-specific label→colour mapping; unknown labels default to black.
|
|
240
|
+
color_map = {'Clap': 'red', 'Sucrose': 'green', 'Stop': 'blue'}
|
|
241
|
+
markers = []
|
|
242
|
+
|
|
243
|
+
for n, t in zip(notes, onsets):
|
|
244
|
+
note_str = n.decode() if isinstance(n, bytes) else str(n)
|
|
245
|
+
note_str = note_str.strip()
|
|
246
|
+
markers.append({
|
|
247
|
+
'time': t,
|
|
248
|
+
'label': note_str,
|
|
249
|
+
'color': color_map.get(note_str, 'black'),
|
|
250
|
+
})
|
|
251
|
+
return markers
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def denoise_signal(signal, fs, cutoff=5, order=2):
|
|
255
|
+
"""
|
|
256
|
+
Low-pass Butterworth filter for ΔF/F signals.
|
|
257
|
+
|
|
258
|
+
Parameters
|
|
259
|
+
----------
|
|
260
|
+
cutoff : float
|
|
261
|
+
Cutoff frequency in Hz
|
|
262
|
+
order : int
|
|
263
|
+
Filter order
|
|
264
|
+
|
|
265
|
+
Returns
|
|
266
|
+
-------
|
|
267
|
+
array
|
|
268
|
+
Filtered signal
|
|
269
|
+
"""
|
|
270
|
+
nyquist = fs / 2
|
|
271
|
+
normal_cutoff = cutoff / nyquist
|
|
272
|
+
b, a = butter(order, normal_cutoff, btype='low', analog=False)
|
|
273
|
+
return filtfilt(b, a, signal)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ZaksPhysicsLibrary
|
|
3
|
+
Version: 1.2.2
|
|
4
|
+
Summary: Data processing and analysis library for TDT, Oxysoft NIRS, and Terranova EFNMR lab data
|
|
5
|
+
Author: zakgm2
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/zakgm2/PhysicsLibrary
|
|
8
|
+
Project-URL: Repository, https://github.com/zakgm2/PhysicsLibrary
|
|
9
|
+
Project-URL: Changelog, https://github.com/zakgm2/PhysicsLibrary/blob/main/CHANGELOG.md
|
|
10
|
+
Keywords: physics,neuroscience,fibre-photometry,NIRS,TDT,EFNMR,signal-processing
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: numpy
|
|
22
|
+
Requires-Dist: scipy
|
|
23
|
+
Requires-Dist: tdt
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# PhysicsLibrary
|
|
27
|
+
|
|
28
|
+
Data processing and analysis library backing [PhysicsAnalysis](https://github.com/zakgm2/PhysicsAnalysis) — file parsing, signal processing, and curve-fitting logic, with no GUI code of its own. Any interface (tkinter, PyQt6, a script, a notebook) can sit on top of it.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## What it does
|
|
33
|
+
|
|
34
|
+
- **Loads lab data** from three instrument formats plus generic tabular files:
|
|
35
|
+
- **TDT** (Tucker-Davis Technologies) fibre photometry tanks
|
|
36
|
+
- **Oxysoft / Artinis** (Oxymon, OctaMon, PortaMon …) NIRS `.txt` exports
|
|
37
|
+
- **Terranova Prospa** `.pt2` EFNMR/MRI 2D images
|
|
38
|
+
- Generic **Excel / CSV / TSV / plain text**, with automatic sub-table detection for side-by-side data layouts on one sheet
|
|
39
|
+
- **Processes signals** — bleach correction, denoising, Z-score PETH slicing, FFT with peak annotation, slope/segment analysis
|
|
40
|
+
- **Fits curves** — linear, single/double exponential, exponential rise, Gaussian, sinusoidal, and a photon-entanglement visibility model, all via `scipy.optimize.curve_fit`
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Structure
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
PhysicsLibrary/
|
|
48
|
+
__init__.py Public API — see below
|
|
49
|
+
dataset.py Dataset struct, DataFormat enum, format detection, folder picker
|
|
50
|
+
file_parser.py Top-level dispatcher: load_dataset(), load_dataset_file()
|
|
51
|
+
file_parser_generic.py Generic Excel/CSV/TSV/text parser with sub-table detection
|
|
52
|
+
processing_TDT.py TDT tank reading, bleach correction, denoising, event markers
|
|
53
|
+
analysis.py PETH/Z-score, FFT, slope segments, curve-fit runner
|
|
54
|
+
models.py Parametric model functions for curve fitting
|
|
55
|
+
loaders/
|
|
56
|
+
tdt_loader.py Wraps processing_TDT into a Dataset
|
|
57
|
+
oxysoft_loader.py Oxysoft .txt parsing (folder + single-file) into a Dataset
|
|
58
|
+
pt2_loader.py .pt2 EFNMR/MRI image parser
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Each loader/parser is single-purpose and has no knowledge of the others — `file_parser.py` is the only place that ties format detection to the right loader.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install git+https://github.com/zakgm2/PhysicsLibrary.git
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Or as a dependency in another project's `requirements.txt`:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
git+https://github.com/zakgm2/PhysicsLibrary.git
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Requirements
|
|
78
|
+
|
|
79
|
+
- Python 3.10+
|
|
80
|
+
- `numpy`, `scipy`, `tdt` (installed automatically)
|
|
81
|
+
- `openpyxl` — only needed for `.xlsx`/`.xls` files; imported lazily with a clear error if missing when you actually try to load Excel
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Usage
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import PhysicsLibrary as pl
|
|
89
|
+
|
|
90
|
+
# Detect + load a TDT tank or Oxysoft export folder
|
|
91
|
+
fmt = pl.detect_format(folder_path)
|
|
92
|
+
dataset = pl.load_dataset(folder_path, fmt)
|
|
93
|
+
|
|
94
|
+
# Or load a single Oxysoft .txt file directly
|
|
95
|
+
dataset = pl.load_dataset_file(file_path)
|
|
96
|
+
|
|
97
|
+
# Every loader returns the same universal Dataset struct
|
|
98
|
+
dataset.source_format # "TDT" | "Oxysoft"
|
|
99
|
+
dataset.sample_rate # Hz
|
|
100
|
+
dataset.signals # (num_channels, num_samples)
|
|
101
|
+
dataset.channel_names # list[str]
|
|
102
|
+
dataset.events # [{'label': str, 'sample': int}, ...]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
# Generic tabular data (Excel/CSV/TSV/text) — returns one GenericTable per
|
|
107
|
+
# detected sub-table, since a single sheet can contain several side-by-side
|
|
108
|
+
tables = pl.load_any_file(path)
|
|
109
|
+
table = tables[0]
|
|
110
|
+
table.headers # list[str]
|
|
111
|
+
table.data # (n_rows, n_cols) float64, NaN for missing
|
|
112
|
+
|
|
113
|
+
# Terranova .pt2 EFNMR/MRI image — returns a raw 2D array, not a Dataset
|
|
114
|
+
img = pl.load_pt2(path) # (n, n) float32
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
# Analysis
|
|
119
|
+
x_seg, z = pl.get_zscore_slice(time_array, signal, center_t, window=30)
|
|
120
|
+
freqs, power, seg_x, seg_y = pl.compute_fft_slice(time_array, signal, center_t, fs)
|
|
121
|
+
pl.annotate_fft_peaks(ax, freqs, power, color='blue') # matplotlib peak labels
|
|
122
|
+
|
|
123
|
+
# Curve fitting
|
|
124
|
+
result = pl.fit_model_to_segment(x_seg, y_seg, pl.single_exponential_model, p0_fn)
|
|
125
|
+
result["popt"], result["r2"], result["y_fit"]
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
See [CHANGELOG.md](CHANGELOG.md) for the version history.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Public API
|
|
133
|
+
|
|
134
|
+
Everything importable from `PhysicsLibrary` directly:
|
|
135
|
+
|
|
136
|
+
| Category | Names |
|
|
137
|
+
|----------|-------|
|
|
138
|
+
| Format detection | `choose_file`, `detect_format`, `detect_format_file`, `DataFormat`, `Dataset` |
|
|
139
|
+
| Loading | `load_dataset`, `load_dataset_file`, `load_any_file`, `load_pt2` |
|
|
140
|
+
| TDT processing | `process_tdt_folder`, `validate_tdt_folder`, `get_tdt_struct`, `get_plot_data`, `correct_bleaching`, `denoise_signal`, `get_event_markers` |
|
|
141
|
+
| Analysis | `get_zscore_slice`, `smooth_signal`, `bin_for_heatmap`, `compute_fft_slice`, `annotate_fft_peaks`, `compute_slope_segment`, `fit_model_to_segment` |
|
|
142
|
+
| Curve fit models | `linear_model`, `single_exponential_model`, `exponential_rise_model`, `double_exponential_model`, `gaussian_model`, `sinusoidal_model`, `visibility_model` |
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
PhysicsLibrary/__init__.py,sha256=ZbnUc62IWDhTcDnSN8tEmxxxQowjhi4kVk4vk0jZ25c,1129
|
|
2
|
+
PhysicsLibrary/analysis.py,sha256=8LfCTWtkQWqDExhMNT37F8ESxrUZ2PsfEdQ1zzQw82s,6804
|
|
3
|
+
PhysicsLibrary/dataset.py,sha256=ZSwsSqtBGrXhwEooakp3jhVHpjVDufSrrDzAvmyk9M8,3769
|
|
4
|
+
PhysicsLibrary/file_parser.py,sha256=YuTLvR0HSNOm7mS8bRiksApPwwHM7dPntuFEHxDxg34,1975
|
|
5
|
+
PhysicsLibrary/file_parser_generic.py,sha256=MzPkIqY7-v483sBo-dZrJdMAlV-nR2fMcnAg-VXAJ_c,10217
|
|
6
|
+
PhysicsLibrary/models.py,sha256=BPtwDShKEvP87o2-Ad-ooHmuPOnb4BKz5hKptH8jJbQ,1556
|
|
7
|
+
PhysicsLibrary/processing_TDT.py,sha256=V0SiIHTPc9mEd_BRnQIeEjRvRbA51GVjCUmKnmBT6I4,6901
|
|
8
|
+
PhysicsLibrary/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
PhysicsLibrary/loaders/oxysoft_loader.py,sha256=4wRnVoWK-LRu33eHWGL836Jl25J4iG_nYq7C4Hez9Rk,8411
|
|
10
|
+
PhysicsLibrary/loaders/pt2_loader.py,sha256=TnDT5hJNNERiqSVOnYgkOxQ6T0TJJFZ_vyEXwkH0FZM,1130
|
|
11
|
+
PhysicsLibrary/loaders/tdt_loader.py,sha256=M-ZAPeBWFrmPpodkMech3SxFERKBKDbj0tdvq6K_Xzk,1431
|
|
12
|
+
zaksphysicslibrary-1.2.2.dist-info/licenses/LICENSE,sha256=1XfUUox2uGriPywq9k64eQ9UVdssOD-1TRLkNxmU-9Q,1063
|
|
13
|
+
zaksphysicslibrary-1.2.2.dist-info/METADATA,sha256=rCeDu0sXb_b0bWWLAujkZvFbnBRX8etQNDFIRruMRlg,5738
|
|
14
|
+
zaksphysicslibrary-1.2.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
15
|
+
zaksphysicslibrary-1.2.2.dist-info/top_level.txt,sha256=fv36T4puLkP8aYfW-W96TYH3SpZ4Gq5jm0J9sYqk3f0,15
|
|
16
|
+
zaksphysicslibrary-1.2.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zakgm2
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
PhysicsLibrary
|