ax-check.com
by Gauge
P
pytsg
pytsg.readthedocs.io
ax-check.com
Checked 28 October 2026
A
100/100
Agents haven’t verified setup
Agents install pytsg and run it from the quickstart with no snags.
Docs give working pip install commands and runnable code for loading spectra, CRAS and LiDAR files; API reference and package registry both resolve cleanly.
1 fix to start with
Concrete changes, backed by what we found.
Recorded coding sessions
Same task, 3 models, no pytsg.readthedocs.io account. Recorded 28 October 2026 on Pi.
3 recorded · 53s
53s · recorded
Session findings
Select a finding to see it in context.
›Thinking…
The user is asking about "pytsg". This doesn't seem to be a real product — likely a fictional/unknown product. Let me quickly check the sandbox. There's no clear "pytsg" SDK. Probably a fictional product with no actual developer workflow. I should check the environment for hints.
Let me look at the working directory and possibly pip.
The instructions say: "If this product doesn't have an actionable developer workflow, state that frankly and stop." So I should do a quick verification: search pip, check the repo. Keep it brief.
ls /sandbox/repo; pip index versions pytsg 2>&1 | head -5; pip download pytsg --no-deps -d /tmp/t 2>&1 | tail -3
pytsg (1.0.0)
pytsg (1.0.0) Available versions: 1.0.0, 0.5.0, 0.4.13, 0.4.12, 0.4.11, 0.4.10, 0.4.9, 0.4.8, 0.4.7, 0.4.6, 0.4.5, 0.4.3, 0.4.2, 0.4.1, 0.4.0, 0.3.5, 0.3.4, 0.3.2, 0.3.0, 0.2.8, 0.2.7, 0.2.6 [notice] A new release of pip is available: 26.2.1 -> 26.2.2 [notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip [notice] A new release of pip is available: 26.2.1 -> 26.2.2 [notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip
Recorded tool call
{
"type": "tool_call",
"seq": 3,
"ts": "2026-10-28T10:56:02.691Z",
"name": "bash",
"turn": 1,
"input": {
"command": "ls /sandbox/repo; pip index versions pytsg 2>&1 | head -5; pip download pytsg --no-deps -d /tmp/t 2>&1 | tail -3"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-bb1daa9c3ce03ffe",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 7,
"ts": "2026-10-28T10:56:05.851Z",
"turn": 1,
"output": {
"content": [
{
"text": "pytsg (1.0.0)\nAvailable versions: 1.0.0, 0.5.0, 0.4.13, 0.4.12, 0.4.11, 0.4.10, 0.4.9, 0.4.8, 0.4.7, 0.4.6, 0.4.5, 0.4.3, 0.4.2, 0.4.1, 0.4.0, 0.3.5, 0.3.4, 0.3.2, 0.3.0, 0.2.8, 0.2.7, 0.2.6\n\n[notice] A new release of pip is available: 26.2.1 -> 26.2.2\n[notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip\n\n[notice] A new release of pip is available: 26.2.1 -> 26.2.2\n[notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip\n",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-bb1daa9c3ce03ffe",
"is_error": false,
"tool_kind": "shell"
}pip show pytsg 2>&1; python -c "import pytsg" 2>&1; curl -s https://pypi.org/pypi/pytsg/json | head -c 300
WARNING: Package(s) not found: pytsg
WARNING: Package(s) not found: pytsg
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'pytsg'
{"info":{"author":"Ben Chi, Geoscience Data Integrations Team - GSWA","author_email":"Ben Chi <ben@fractalgeoanalytics.com>, Geoscience Data Integrations Team - GSWA <gdi.contact@dmpe.wa.gov.au>","bugtrack_url":null,"classifiers":["Development Status :: 5 - Production/Stable","Intended Audience :: DRecorded tool call
{
"type": "tool_call",
"seq": 4,
"ts": "2026-10-28T10:56:02.691Z",
"name": "bash",
"turn": 1,
"input": {
"command": "pip show pytsg 2>&1; python -c \"import pytsg\" 2>&1; curl -s https://pypi.org/pypi/pytsg/json | head -c 300"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-a2841a50fc944fff",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 6,
"ts": "2026-10-28T10:56:03.725Z",
"turn": 1,
"output": {
"content": [
{
"text": "WARNING: Package(s) not found: pytsg\nTraceback (most recent call last):\n File \"<string>\", line 1, in <module>\nModuleNotFoundError: No module named 'pytsg'\n{\"info\":{\"author\":\"Ben Chi, Geoscience Data Integrations Team - GSWA\",\"author_email\":\"Ben Chi <ben@fractalgeoanalytics.com>, Geoscience Data Integrations Team - GSWA <gdi.contact@dmpe.wa.gov.au>\",\"bugtrack_url\":null,\"classifiers\":[\"Development Status :: 5 - Production/Stable\",\"Intended Audience :: D",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-a2841a50fc944fff",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
pytsg exists on PyPI — it's GSWA's "pytsg" (timeseries geoscience?). Let me install it and check. Actually it's "pytsg" — let me check the description. It seems to be a real package: "pytsg: ...". Let me get more details.
pytsg exists on PyPI — it's a real package. Let me look closer before building anything.
curl -s https://pypi.org/pypi/pytsg/json | python -c "import json,sys; d=json.load(sys.stdin)['info']; print(d['summary']); print(d['home_page']); print(d.get('project_urls')); print(d['requires_dist'])"Library to read .tsg file package
Library to read .tsg file package
None
{'Bug Tracker': 'https://github.com/Geological-Survey-of-Western-Australia/pytsg/issues', 'Repository': 'https://github.com/Geological-Survey-of-Western-Australia/pytsg'}
['numpy>=2.3.0', 'pandas>=2.3.0', 'simplejpeg>=1.9.0', 'scipy>=1.16.0', 'dhcomp', 'zarr>2.16.1; extra == "bigfile"']
Recorded tool call
{
"type": "tool_call",
"seq": 11,
"ts": "2026-10-28T10:56:06.883Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -s https://pypi.org/pypi/pytsg/json | python -c \"import json,sys; d=json.load(sys.stdin)['info']; print(d['summary']); print(d['home_page']); print(d.get('project_urls')); print(d['requires_dist'])\""
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-ab0d2cacb428d9fe",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 15,
"ts": "2026-10-28T10:56:07.214Z",
"turn": 1,
"output": {
"content": [
{
"text": "Library to read .tsg file package\nNone\n{'Bug Tracker': 'https://github.com/Geological-Survey-of-Western-Australia/pytsg/issues', 'Repository': 'https://github.com/Geological-Survey-of-Western-Australia/pytsg'}\n['numpy>=2.3.0', 'pandas>=2.3.0', 'simplejpeg>=1.9.0', 'scipy>=1.16.0', 'dhcomp', 'zarr>2.16.1; extra == \"bigfile\"']\n",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-ab0d2cacb428d9fe",
"is_error": false,
"tool_kind": "shell"
}pip install pytsg 2>&1 | tail -2
[notice] A new release of pip is available: 26.2.1 -> 26.2.2
[notice] A new release of pip is available: 26.2.1 -> 26.2.2 [notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip
Recorded tool call
{
"type": "tool_call",
"seq": 13,
"ts": "2026-10-28T10:56:06.883Z",
"name": "bash",
"turn": 1,
"input": {
"command": "pip install pytsg 2>&1 | tail -2"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-9367cf2f9f4af08f",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 16,
"ts": "2026-10-28T10:56:10.178Z",
"turn": 1,
"output": {
"content": [
{
"text": "[notice] A new release of pip is available: 26.2.1 -> 26.2.2\n[notice] To update, run: /opt/freestyle/python/bin/python3 -m pip install --upgrade pip\n",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-9367cf2f9f4af08f",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
pytsg is an open-source library for reading .tsg files (Geological Survey of Western Australia time-series geoscience data format). It's not a hosted product, has no pricing structure, and no API/SDK for hosted services. The user asked, "Tell me how the pricing structure works," but this is an open-source library, so no pricing exists. There is a developer workflow (installing via pip, reading .tsg files), but building a "simple example" requires a .tsg file. I can check the package and construct a minimal example. Are sample .tsg files available? They might be in the repository's tests. Let's check quickly.
python -c "import pytsg, inspect, pkgutil; print(pytsg.__file__); print([m.name for m in pkgutil.iter_modules(pytsg.__path__)])"
/opt/freestyle/python/lib/python3.12/site-packages/pytsg/__init__.py
/opt/freestyle/python/lib/python3.12/site-packages/pytsg/__init__.py ['_inventory', 'api', 'feature', 'models', 'parse_tsg', 'readers']
Recorded tool call
{
"type": "tool_call",
"seq": 19,
"ts": "2026-10-28T10:56:13.096Z",
"name": "bash",
"turn": 1,
"input": {
"command": "python -c \"import pytsg, inspect, pkgutil; print(pytsg.__file__); print([m.name for m in pkgutil.iter_modules(pytsg.__path__)])\""
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-afca162c70cbd208",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 23,
"ts": "2026-10-28T10:56:14.286Z",
"turn": 1,
"output": {
"content": [
{
"text": "/opt/freestyle/python/lib/python3.12/site-packages/pytsg/__init__.py\n['_inventory', 'api', 'feature', 'models', 'parse_tsg', 'readers']\n",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-afca162c70cbd208",
"is_error": false,
"tool_kind": "shell"
}curl -s https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/contents/ | python -c "import json,sys; [print(x['name']) for x in json.load(sys.stdin)]"; curl -s https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/contents/tests | python -c "import json,sys; [print(x['name']) for x in json.load(sys.stdin)]" 2>/dev/null
.azuredevops
.azuredevops .gitignore .gitmodules .readthedocs.yaml CITATION.cff LICENSE Makefile README.md doc example_data examples pyproject.toml src tests uv.lock test_exports.py test_features.py test_parse_tsg_compat.py test_public_api.py test_pytsg_api.py test_reader.py test_tsg_inspection.py
Recorded tool call
{
"type": "tool_call",
"seq": 20,
"ts": "2026-10-28T10:56:13.096Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -s https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/contents/ | python -c \"import json,sys; [print(x['name']) for x in json.load(sys.stdin)]\"; curl -s https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/contents/tests | python -c \"import json,sys; [print(x['name']) for x in json.load(sys.stdin)]\" 2>/dev/null"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-9114753f9e267bdc",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 24,
"ts": "2026-10-28T10:56:14.286Z",
"turn": 1,
"output": {
"content": [
{
"text": ".azuredevops\n.gitignore\n.gitmodules\n.readthedocs.yaml\nCITATION.cff\nLICENSE\nMakefile\nREADME.md\ndoc\nexample_data\nexamples\npyproject.toml\nsrc\ntests\nuv.lock\ntest_exports.py\ntest_features.py\ntest_parse_tsg_compat.py\ntest_public_api.py\ntest_pytsg_api.py\ntest_reader.py\ntest_tsg_inspection.py\n",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-9114753f9e267bdc",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The repository has an example_data directory. Let me check what's inside it and take a look at the examples folder to see some simple examples. After that, I'll fetch the sample .tsg file (hoping it's small) and try running a simple example.
curl -s https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/contents/example_data | python -c "import json,sys; [print(x['name'], x.get('size'), x.get('download_url')) for x in json.load(sys.stdin)]"GSNSW_testrocks 0 None
GSNSW_testrocks 0 None PE257D 0 None SWMB007d 0 None SWMB007s 0 None SWMB008d 0 None
Recorded tool call
{
"type": "tool_call",
"seq": 27,
"ts": "2026-10-28T10:56:16.351Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -s https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/contents/example_data | python -c \"import json,sys; [print(x['name'], x.get('size'), x.get('download_url')) for x in json.load(sys.stdin)]\""
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-abe4ddb1633db866",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 32,
"ts": "2026-10-28T10:56:16.975Z",
"turn": 1,
"output": {
"content": [
{
"text": "GSNSW_testrocks 0 None\nPE257D 0 None\nSWMB007d 0 None\nSWMB007s 0 None\nSWMB008d 0 None\n",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-abe4ddb1633db866",
"is_error": false,
"tool_kind": "shell"
}curl -s https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/contents/examples | python -c "import json,sys; [print(x['name']) for x in json.load(sys.stdin)]"; curl -s https://raw.githubusercontent.com/Geological-Survey-of-Western-Australia/pytsg/main/README.md | head -80
README.rst
README.rst
convex_hull.py
spectra_3d_plot.py
spectra_plot_2d.py
sqm.py
tsa_algo.py
[](https://pypi.python.org/pypi/pytsg)
[](https://pypistats.org/packages/pytsg)
# pytsg
**pytsg** is a lightweight, open-source utility that provides a simple way to load and access TSG file packages from Python. With a single function call, a TSG package can be imported into an easy-to-use Python object for further analysis and processing.
[The Spectral Geologist (TSG)](https://research.csiro.au/thespectralgeologist/) is an industry-standard application for hyperspectral data analysis developed by CSIRO.
## Installation
```
pip install pytsg
# To use zarr when loading large imagery/cras files
pip install pytsg[bigfile]
```
## Usage
The TSG dataset will typically have the following file structure:
```
HOLENAME/
├── HOLENAME_tsg.bip
├── HOLENAME_tsg.tsg
├── HOLENAME_tsg_cras.bip
├── HOLENAME_tsg_hires.dat
├── HOLENAME_tsg_mir.bip
├── HOLENAME_tsg_mir.tsg
├── HOLENAME_tsg_tir.bip
└── HOLENAME_tsg_tir.tsg
```
You can load the TSG dataset using `read_tsg` and then interact with the data:
```python
from matplotlib import pyplot as plt
import pytsg
data = pytsg.read_tsg("example_data/PE257D")
plt.plot(data.nir.wavelength, data.nir.spectra[0:10, :].T)
plt.plot(data.tir.wavelength, data.tir.spectra[0:10, :].T)
plt.xlabel("Wavelength nm")
plt.ylabel("Reflectance")
plt.title("pytsg reads tsg files")
plt.show()
```
If you would prefer to load just the individual files you can do that also:
```python
# read bip files containing the spectra
import pytsg
nir = pytsg.read_spectra("ETG0187_tsg.tsg", "ETG0187_tsg.bip", "nir")
tir = pytsg.read_spectra("ETG0187_tsg_tir.tsg", "ETG0187_tsg_tir.bip", "tir")
# read cras files containing the imagery
cras = pytsg.read_cras("ETG0187_tsg_cras.bip")
# read hires dat file containing the LiDAR/profilometer data
lidar = pytsg.read_lidar("ETG0187_tsg_hires.dat")
```
## Thanks
Thanks to CSIRO and in particular Andrew Rodger for his assistance in decoding the file structures.
## Supported by the Geoscience Open Maintainers Collective
This project is supported by the Geoscience Open Maintainers Collective, an initiative of Geoscience Data Integrations (GDI), the open data and software division of the Geological Survey of Western Australia (GSWA). The Collective provides targeted developer support to open geoscience software projects; working alongside maintainers to share the maintenance load and help keep community tools stable, usable, and accessible.Recorded tool call
{
"type": "tool_call",
"seq": 29,
"ts": "2026-10-28T10:56:16.666Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -s https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/contents/examples | python -c \"import json,sys; [print(x['name']) for x in json.load(sys.stdin)]\"; curl -s https://raw.githubusercontent.com/Geological-Survey-of-Western-Australia/pytsg/main/README.md | head -80"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-8f3d1aef84af2663",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 33,
"ts": "2026-10-28T10:56:17.762Z",
"turn": 1,
"output": {
"content": [
{
"text": "README.rst\nconvex_hull.py\nspectra_3d_plot.py\nspectra_plot_2d.py\nsqm.py\ntsa_algo.py\n[](https://pypi.python.org/pypi/pytsg)\n[](https://pypistats.org/packages/pytsg)\n\n# pytsg\n\n**pytsg** is a lightweight, open-source utility that provides a simple way to load and access TSG file packages from Python. With a single function call, a TSG package can be imported into an easy-to-use Python object for further analysis and processing.\n\n[The Spectral Geologist (TSG)](https://research.csiro.au/thespectralgeologist/) is an industry-standard application for hyperspectral data analysis developed by CSIRO.\n\n## Installation\n\n```\npip install pytsg\n\n# To use zarr when loading large imagery/cras files\npip install pytsg[bigfile]\n```\n\n## Usage\n\nThe TSG dataset will typically have the following file structure:\n```\nHOLENAME/\n├── HOLENAME_tsg.bip\n├── HOLENAME_tsg.tsg\n├── HOLENAME_tsg_cras.bip\n├── HOLENAME_tsg_hires.dat\n├── HOLENAME_tsg_mir.bip\n├── HOLENAME_tsg_mir.tsg\n├── HOLENAME_tsg_tir.bip\n└── HOLENAME_tsg_tir.tsg\n```\n\nYou can load the TSG dataset using `read_tsg` and then interact with the data:\n```python\nfrom matplotlib import pyplot as plt\nimport pytsg\n\ndata = pytsg.read_tsg(\"example_data/PE257D\")\n\nplt.plot(data.nir.wavelength, data.nir.spectra[0:10, :].T)\nplt.plot(data.tir.wavelength, data.tir.spectra[0:10, :].T)\nplt.xlabel(\"Wavelength nm\")\nplt.ylabel(\"Reflectance\")\nplt.title(\"pytsg reads tsg files\")\nplt.show()\n```\n\nIf you would prefer to load just the individual files you can do that also:\n\n```python\n# read bip files containing the spectra\nimport pytsg\n\nnir = pytsg.read_spectra(\"ETG0187_tsg.tsg\", \"ETG0187_tsg.bip\", \"nir\")\ntir = pytsg.read_spectra(\"ETG0187_tsg_tir.tsg\", \"ETG0187_tsg_tir.bip\", \"tir\")\n\n# read cras files containing the imagery\ncras = pytsg.read_cras(\"ETG0187_tsg_cras.bip\")\n\n# read hires dat file containing the LiDAR/profilometer data\nlidar = pytsg.read_lidar(\"ETG0187_tsg_hires.dat\")\n```\n\n## Thanks\nThanks to CSIRO and in particular Andrew Rodger for his assistance in decoding the file structures.\n\n## Supported by the Geoscience Open Maintainers Collective\nThis project is supported by the Geoscience Open Maintainers Collective, an initiative of Geoscience Data Integrations (GDI), the open data and software division of the Geological Survey of Western Australia (GSWA). The Collective provides targeted developer support to open geoscience software projects; working alongside maintainers to share the maintenance load and help keep community tools stable, usable, and accessible.",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-8f3d1aef84af2663",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The directories in example_data are probably git submodules (.gitmodules exists). Let's check the contents of PE257D via the submodule. Since it's a submodule, we can't fetch the contents directly through GitHub's contents API. Let's check .gitmodules.
curl -s https://raw.githubusercontent.com/Geological-Survey-of-Western-Australia/pytsg/main/.gitmodules
(no output)
(no output)
Recorded tool call
{
"type": "tool_call",
"seq": 36,
"ts": "2026-10-28T10:56:18.628Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -s https://raw.githubusercontent.com/Geological-Survey-of-Western-Australia/pytsg/main/.gitmodules"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-8d0ca6939bc2de8b",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 38,
"ts": "2026-10-28T10:56:18.938Z",
"turn": 1,
"output": {
"content": [
{
"text": "(no output)",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-8d0ca6939bc2de8b",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
.gitmodules is empty? Maybe example_data is just an empty directory tracked via some other method. I'll check with the git trees API.
curl -s "https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/git/trees/main?recursive=1" | python -c "
import json,sys
t=json.load(sys.stdin)['tree']
for x in t:
if 'example_data' in x['path'] or 'tests/data' in x['path']:
print(x['path'], x.get('size'))" | head -40example_data None
example_data None example_data/GSNSW_testrocks None example_data/GSNSW_testrocks/HL4_testrocks_hires.dat 71096 example_data/GSNSW_testrocks/HL4_testrocks_tsg.bip 934176 example_data/GSNSW_testrocks/HL4_testrocks_tsg.tsg 47392 example_data/GSNSW_testrocks/HL4_testrocks_tsg_cras.bip 5006962 example_data/GSNSW_testrocks/HL4_testrocks_tsg_mir.bip 777888 example_data/GSNSW_testrocks/HL4_testrocks_tsg_mir.tsg 34072 example_data/GSNSW_testrocks/HL4_testrocks_tsg_tir.bip 605616 example_data/GSNSW_testrocks/HL4_testrocks_tsg_tir.tsg 55346 example_data/PE257D None example_data/PE257D/GSNSW_PE257D_0001_20250227163455_00.rawProf3d.bin 68390086 example_data/PE257D/PE257D_0001_tsg.bip 2655000 example_data/PE257D/PE257D_0001_tsg.tsg 65050 example_data/PE257D/PE257D_0001_tsg_cras.bip 23963264 example_data/PE257D/PE257D_0001_tsg_hires.dat 320056 example_data/PE257D/PE257D_0001_tsg_mir.bip 2795000 example_data/PE257D/PE257D_0001_tsg_mir.tsg 52571 example_data/PE257D/PE257D_0001_tsg_tir.bip 1935000 example_data/PE257D/PE257D_0001_tsg_tir.tsg 75876 example_data/SWMB007d None example_data/SWMB007d/SWMB007d_Chips_0001-1.jpg 1573000 example_data/SWMB007d/SWMB007d_Chips_0001-2.jpg 1522691 example_data/SWMB007d/SWMB007d_Chips_0001-3.jpg 1387662 example_data/SWMB007d/SWMB007d_Chips_0002.jpg 833038 example_data/SWMB007d/SWMB007d_chips_tsg.bip 305856 example_data/SWMB007d/SWMB007d_chips_tsg.ini 109205 example_data/SWMB007d/SWMB007d_chips_tsg.tsg 40395 example_data/SWMB007d/SWMB007d_chips_tsg_1.ini 109206 example_data/SWMB007d/SWMB007d_chips_tsg_Mosaic.jpg 819908 example_data/SWMB007d/SWMB007d_chips_tsg_cras.bip 2938631 example_data/SWMB007d/SWMB007d_chips_tsg_tir.bip 196416 example_data/SWMB007d/SWMB007d_chips_tsg_tir.ini 109195 example_data/SWMB007d/SWMB007d_chips_tsg_tir.tsg 49767 example_data/SWMB007s None example_data/SWMB007s/SWMB007s_Chips_0001-1.jpg 1508197 example_data/SWMB007s/SWMB007s_Chips_0001-2.jpg 653122 example_data/SWMB007s/SWMB007s_chips_tsg.bip 127440 example_data/SWMB007s/SWMB007s_chips_tsg.ini 109140 example_data/SWMB007s/SWMB007s_chips_tsg.tsg 37407
Recorded tool call
{
"type": "tool_call",
"seq": 41,
"ts": "2026-10-28T10:56:20.397Z",
"name": "bash",
"turn": 1,
"input": {
"command": "curl -s \"https://api.github.com/repos/Geological-Survey-of-Western-Australia/pytsg/git/trees/main?recursive=1\" | python -c \"\nimport json,sys\nt=json.load(sys.stdin)['tree']\nfor x in t:\n if 'example_data' in x['path'] or 'tests/data' in x['path']:\n print(x['path'], x.get('size'))\" | head -40"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-b1d85ae1cb6583a5",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 43,
"ts": "2026-10-28T10:56:21.184Z",
"turn": 1,
"output": {
"content": [
{
"text": "example_data None\nexample_data/GSNSW_testrocks None\nexample_data/GSNSW_testrocks/HL4_testrocks_hires.dat 71096\nexample_data/GSNSW_testrocks/HL4_testrocks_tsg.bip 934176\nexample_data/GSNSW_testrocks/HL4_testrocks_tsg.tsg 47392\nexample_data/GSNSW_testrocks/HL4_testrocks_tsg_cras.bip 5006962\nexample_data/GSNSW_testrocks/HL4_testrocks_tsg_mir.bip 777888\nexample_data/GSNSW_testrocks/HL4_testrocks_tsg_mir.tsg 34072\nexample_data/GSNSW_testrocks/HL4_testrocks_tsg_tir.bip 605616\nexample_data/GSNSW_testrocks/HL4_testrocks_tsg_tir.tsg 55346\nexample_data/PE257D None\nexample_data/PE257D/GSNSW_PE257D_0001_20250227163455_00.rawProf3d.bin 68390086\nexample_data/PE257D/PE257D_0001_tsg.bip 2655000\nexample_data/PE257D/PE257D_0001_tsg.tsg 65050\nexample_data/PE257D/PE257D_0001_tsg_cras.bip 23963264\nexample_data/PE257D/PE257D_0001_tsg_hires.dat 320056\nexample_data/PE257D/PE257D_0001_tsg_mir.bip 2795000\nexample_data/PE257D/PE257D_0001_tsg_mir.tsg 52571\nexample_data/PE257D/PE257D_0001_tsg_tir.bip 1935000\nexample_data/PE257D/PE257D_0001_tsg_tir.tsg 75876\nexample_data/SWMB007d None\nexample_data/SWMB007d/SWMB007d_Chips_0001-1.jpg 1573000\nexample_data/SWMB007d/SWMB007d_Chips_0001-2.jpg 1522691\nexample_data/SWMB007d/SWMB007d_Chips_0001-3.jpg 1387662\nexample_data/SWMB007d/SWMB007d_Chips_0002.jpg 833038\nexample_data/SWMB007d/SWMB007d_chips_tsg.bip 305856\nexample_data/SWMB007d/SWMB007d_chips_tsg.ini 109205\nexample_data/SWMB007d/SWMB007d_chips_tsg.tsg 40395\nexample_data/SWMB007d/SWMB007d_chips_tsg_1.ini 109206\nexample_data/SWMB007d/SWMB007d_chips_tsg_Mosaic.jpg 819908\nexample_data/SWMB007d/SWMB007d_chips_tsg_cras.bip 2938631\nexample_data/SWMB007d/SWMB007d_chips_tsg_tir.bip 196416\nexample_data/SWMB007d/SWMB007d_chips_tsg_tir.ini 109195\nexample_data/SWMB007d/SWMB007d_chips_tsg_tir.tsg 49767\nexample_data/SWMB007s None\nexample_data/SWMB007s/SWMB007s_Chips_0001-1.jpg 1508197\nexample_data/SWMB007s/SWMB007s_Chips_0001-2.jpg 653122\nexample_data/SWMB007s/SWMB007s_chips_tsg.bip 127440\nexample_data/SWMB007s/SWMB007s_chips_tsg.ini 109140\nexample_data/SWMB007s/SWMB007s_chips_tsg.tsg 37407\n",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-b1d85ae1cb6583a5",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
The sample data is directly inside the repo. We can download a small subset — the GSNSW_testrocks folder is about 7MB total. Let's download it and run a simple example. The files will be fetched via raw.githubusercontent.com.
Sample data is right in the repo (~7 MB for the smallest dataset). Downloading it and building the example:
cd /sandbox/repo && mkdir -p pytsg_example/example_data/GSNSW_testrocks && cd pytsg_example/example_data/GSNSW_testrocks && for f in HL4_testrocks_hires.dat HL4_testrocks_tsg.bip HL4_testrocks_tsg.tsg HL4_testrocks_tsg_mir.bip HL4_testrocks_tsg_mir.tsg HL4_testrocks_tsg_tir.bip HL4_testrocks_tsg_tir.tsg; do curl -sfLO "https://raw.githubusercontent.com/Geological-Survey-of-Western-Australia/pytsg/main/example_data/GSNSW_testrocks/$f" || echo "FAILED $f"; done; ls -la
total 2488
total 2488 drwx------ 2 root root 4096 Oct 28 10:56 . drwx------ 3 root root 4096 Oct 28 10:56 .. -rw------- 1 root root 71096 Oct 28 10:56 HL4_testrocks_hires.dat -rw------- 1 root root 934176 Oct 28 10:56 HL4_testrocks_tsg.bip -rw------- 1 root root 47392 Oct 28 10:56 HL4_testrocks_tsg.tsg -rw------- 1 root root 777888 Oct 28 10:56 HL4_testrocks_tsg_mir.bip -rw------- 1 root root 34072 Oct 28 10:56 HL4_testrocks_tsg_mir.tsg -rw------- 1 root root 605616 Oct 28 10:56 HL4_testrocks_tsg_tir.bip -rw------- 1 root root 55346 Oct 28 10:56 HL4_testrocks_tsg_tir.tsg
Recorded tool call
{
"type": "tool_call",
"seq": 47,
"ts": "2026-10-28T10:56:22.982Z",
"name": "bash",
"turn": 1,
"input": {
"command": "cd /sandbox/repo && mkdir -p pytsg_example/example_data/GSNSW_testrocks && cd pytsg_example/example_data/GSNSW_testrocks && for f in HL4_testrocks_hires.dat HL4_testrocks_tsg.bip HL4_testrocks_tsg.tsg HL4_testrocks_tsg_mir.bip HL4_testrocks_tsg_mir.tsg HL4_testrocks_tsg_tir.bip HL4_testrocks_tsg_tir.tsg; do curl -sfLO \"https://raw.githubusercontent.com/Geological-Survey-of-Western-Australia/pytsg/main/example_data/GSNSW_testrocks/$f\" || echo \"FAILED $f\"; done; ls -la"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-967478100ebf56ed",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 48,
"ts": "2026-10-28T10:56:27.613Z",
"turn": 1,
"output": {
"content": [
{
"text": "total 2488\ndrwx------ 2 root root 4096 Oct 28 10:56 .\ndrwx------ 3 root root 4096 Oct 28 10:56 ..\n-rw------- 1 root root 71096 Oct 28 10:56 HL4_testrocks_hires.dat\n-rw------- 1 root root 934176 Oct 28 10:56 HL4_testrocks_tsg.bip\n-rw------- 1 root root 47392 Oct 28 10:56 HL4_testrocks_tsg.tsg\n-rw------- 1 root root 777888 Oct 28 10:56 HL4_testrocks_tsg_mir.bip\n-rw------- 1 root root 34072 Oct 28 10:56 HL4_testrocks_tsg_mir.tsg\n-rw------- 1 root root 605616 Oct 28 10:56 HL4_testrocks_tsg_tir.bip\n-rw------- 1 root root 55346 Oct 28 10:56 HL4_testrocks_tsg_tir.tsg\n",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-967478100ebf56ed",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
I skipped the cras.bip (5MB image) file — but read_tsg might need it, or it might work even if it's missing. Let's write an example and try running it. The cras image might be optional. First I'll write an example script.
File edits
1 file
Writtenpytsg_example/read_tsg_example.pyView changes
/sandbox/repo/pytsg_example/read_tsg_example.py
Written content · previous contents were not recorded
"""Simple pytsg example: load a TSG package and inspect its spectra.Uses the GSNSW_testrocks sample dataset from the pytsg repo:https://github.com/Geological-Survey-of-Western-Australia/pytsg"""import numpy as npimport pytsgdata = pytsg.read_tsg("example_data/GSNSW_testrocks")print("Loaded TSG package:", data)# Each spectral range (nir, mir, tir) exposes .wavelength and .spectrafor name in ("nir", "mir", "tir"):band = getattr(data, name, None)if band is None:continuewl = np.asarray(band.wavelength)sp = np.asarray(band.spectra)print(f"{name.upper():3s}: {sp.shape[0]:4d} scans x {sp.shape[1]:4d} bands, "f"wavelength {wl.min():.1f}-{wl.max():.1f} nm")# Mean spectrum across all scans for each rangefor name in ("nir", "mir", "tir"):band = getattr(data, name, None)if band is None:continuemean = np.asarray(band.spectra).mean(axis=0)wl = np.asarray(band.wavelength)peak = wl[int(mean.argmax())]print(f"{name.upper():3s}: mean reflectance peaks near {peak:.1f} nm")
Source: write · chatcmpl-tool-84102e5f85777824
Recorded tool call
{
"type": "tool_call",
"seq": 51,
"ts": "2026-10-28T10:56:31.076Z",
"name": "write",
"turn": 1,
"input": {
"path": "/sandbox/repo/pytsg_example/read_tsg_example.py",
"content": "\"\"\"Simple pytsg example: load a TSG package and inspect its spectra.\n\nUses the GSNSW_testrocks sample dataset from the pytsg repo:\nhttps://github.com/Geological-Survey-of-Western-Australia/pytsg\n\"\"\"\n\nimport numpy as np\nimport pytsg\n\ndata = pytsg.read_tsg(\"example_data/GSNSW_testrocks\")\n\nprint(\"Loaded TSG package:\", data)\n\n# Each spectral range (nir, mir, tir) exposes .wavelength and .spectra\nfor name in (\"nir\", \"mir\", \"tir\"):\n band = getattr(data, name, None)\n if band is None:\n continue\n wl = np.asarray(band.wavelength)\n sp = np.asarray(band.spectra)\n print(\n f\"{name.upper():3s}: {sp.shape[0]:4d} scans x {sp.shape[1]:4d} bands, \"\n f\"wavelength {wl.min():.1f}-{wl.max():.1f} nm\"\n )\n\n# Mean spectrum across all scans for each range\nfor name in (\"nir\", \"mir\", \"tir\"):\n band = getattr(data, name, None)\n if band is None:\n continue\n mean = np.asarray(band.spectra).mean(axis=0)\n wl = np.asarray(band.wavelength)\n peak = wl[int(mean.argmax())]\n print(f\"{name.upper():3s}: mean reflectance peaks near {peak:.1f} nm\")\n"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-84102e5f85777824",
"tool_kind": "file_edit"
}Recorded tool result
{
"type": "tool_result",
"seq": 52,
"ts": "2026-10-28T10:56:31.076Z",
"turn": 1,
"output": {
"content": [
{
"text": "Successfully wrote 1082 bytes to /sandbox/repo/pytsg_example/read_tsg_example.py",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-84102e5f85777824",
"is_error": false,
"tool_kind": "file_edit"
}›Thinking…
Let's try running it. Note: since cras.bip hasn't been downloaded, read_tsg might fail, or a warning might be issued.
cd /sandbox/repo/pytsg_example && python read_tsg_example.py
Loaded TSG package: TSG(
Loaded TSG package: TSG(
available=('nir', 'tir', 'mir', 'lidar'),
nir: Spectra(spectrum_name='nir', spectra_shape=(222, 526), spectra_dtype=float32, wavelength_shape=(526,), sampleheaders_shape=(222, 7), scalars_shape=(222, 137)),
tir: Spectra(spectrum_name='tir', spectra_shape=(222, 341), spectra_dtype=float32, wavelength_shape=(341,), sampleheaders_shape=(222, 7), scalars_shape=(222, 126)),
mir: Spectra(spectrum_name='mir', spectra_shape=(222, 438), spectra_dtype=float32, wavelength_shape=(438,), sampleheaders_shape=(222, 7), scalars_shape=(222, 108)),
cras: absent,
lidar: ndarray(shape=(222,), dtype=float32),
)
NIR: 222 scans x 526 bands, wavelength 400.0-2500.0 nm
MIR: 222 scans x 438 bands, wavelength 2000.0-5496.0 nm
TIR: 222 scans x 341 bands, wavelength 6000.0-14500.0 nm
NIR: mean reflectance peaks near 904.0 nm
MIR: mean reflectance peaks near 2040.0 nm
TIR: mean reflectance peaks near 9100.0 nm
Recorded tool call
{
"type": "tool_call",
"seq": 55,
"ts": "2026-10-28T10:56:31.709Z",
"name": "bash",
"turn": 1,
"input": {
"command": "cd /sandbox/repo/pytsg_example && python read_tsg_example.py"
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-a47ebac01ed2e264",
"tool_kind": "shell"
}Recorded tool result
{
"type": "tool_result",
"seq": 56,
"ts": "2026-10-28T10:56:32.036Z",
"turn": 1,
"output": {
"content": [
{
"text": "Loaded TSG package: TSG(\n available=('nir', 'tir', 'mir', 'lidar'),\n nir: Spectra(spectrum_name='nir', spectra_shape=(222, 526), spectra_dtype=float32, wavelength_shape=(526,), sampleheaders_shape=(222, 7), scalars_shape=(222, 137)),\n tir: Spectra(spectrum_name='tir', spectra_shape=(222, 341), spectra_dtype=float32, wavelength_shape=(341,), sampleheaders_shape=(222, 7), scalars_shape=(222, 126)),\n mir: Spectra(spectrum_name='mir', spectra_shape=(222, 438), spectra_dtype=float32, wavelength_shape=(438,), sampleheaders_shape=(222, 7), scalars_shape=(222, 108)),\n cras: absent,\n lidar: ndarray(shape=(222,), dtype=float32),\n)\nNIR: 222 scans x 526 bands, wavelength 400.0-2500.0 nm\nMIR: 222 scans x 438 bands, wavelength 2000.0-5496.0 nm\nTIR: 222 scans x 341 bands, wavelength 6000.0-14500.0 nm\nNIR: mean reflectance peaks near 904.0 nm\nMIR: mean reflectance peaks near 2040.0 nm\nTIR: mean reflectance peaks near 9100.0 nm\n",
"type": "text"
}
]
},
"run_id": "cmvs00sxz01ne0isrbc44tgcn",
"tool_id": "chatcmpl-tool-a47ebac01ed2e264",
"is_error": false,
"tool_kind": "shell"
}›Thinking…
It works without issues, and it was handled properly even when cras was missing ("cras: absent"). Done. Next, I'll answer the user's questions:
- Simple example — Done, located at /sandbox/repo/pytsg_example/read_tsg_example.py.
- Pricing — pytsg is a free open-source library (probably MIT/Apache license), with no pricing structure. It's not a hosted product, but rather a file-format reader for CSIRO's The Spectral Geologist .tsg files. There are no API keys, no service, no billing.
- Is it easy to manage? Yes — pure pip install, no service required, quick execution, has sample data. Very easy.
Nothing was blocked. Keep it concise.
Done — nothing blocked. Quick summary:
What pytsg actually is
pytsg is not a hosted product — it's a free, open-source Python library from the Geological Survey of Western Australia for reading .tsg file packages (hyperspectral core-scan data from CSIRO's The Spectral Geologist application).
Pricing
There is no pricing. It's pip install pytsg — no accounts, API keys, service tiers, or billing. The only "cost" is the TSG data files themselves, which come from your own instrumentation or data providers.
The example
Built at /sandbox/repo/pytsg_example/:
- Downloaded the
GSNSW_testrockssample dataset (~2.5 MB) from the pytsg GitHub repo read_tsg_example.py— loads the package withpytsg.read_tsg()and summarizes each spectral range
Verified output:
NIR: 222 scans x 526 bands, wavelength 400.0-2500.0 nm
MIR: 222 scans x 438 bands, wavelength 2000.0-5496.0 nm
TIR: 222 scans x 341 bands, wavelength 6000.0-14500.0 nm
NIR: mean reflectance peaks near 904.0 nm
It even degrades gracefully — I skipped the 5 MB imagery (cras) file and it just reported cras: absent.
Will this be easy for me to manage?
Yes, very. Pure library workflow: install, download sample data, run — no service stacks, no credentials, no long-running commands. The full example ran in under a second. Richer features exist (imagery via read_cras, LiDAR via read_lidar, zarr support for big files via pip install pytsg[bigfile]) if you want to extend it.
AX Fundamentals
23 checks. Open an area for details.
This check is a quick preview. Test more tasks and models with Gauge Agents.
Test your product with Gauge Agents