fits2tmp 0.4.0__tar.gz → 1.0.2__tar.gz
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.
- fits2tmp-1.0.2/PKG-INFO +49 -0
- fits2tmp-1.0.2/README.md +26 -0
- fits2tmp-1.0.2/pyproject.toml +38 -0
- fits2tmp-1.0.2/pyproject.toml.orig +37 -0
- fits2tmp-1.0.2/src/fits2tmp/fits2tmp.py +173 -0
- fits2tmp-0.4.0/LICENSE +0 -28
- fits2tmp-0.4.0/PKG-INFO +0 -93
- fits2tmp-0.4.0/README.md +0 -65
- fits2tmp-0.4.0/pyproject.toml +0 -31
- fits2tmp-0.4.0/src/fits2tmp/fits2tmp.py +0 -192
- {fits2tmp-0.4.0 → fits2tmp-1.0.2}/src/fits2tmp/__init__.py +0 -0
- {fits2tmp-0.4.0 → fits2tmp-1.0.2}/src/fits2tmp/dask-output.log +0 -0
- {fits2tmp-0.4.0 → fits2tmp-1.0.2}/src/fits2tmp/sdc2_100.fits +0 -0
- {fits2tmp-0.4.0 → fits2tmp-1.0.2}/src/fits2tmp/sofiatestrewrite1002_cat.txt +0 -0
- {fits2tmp-0.4.0 → fits2tmp-1.0.2}/src/fits2tmp/sofiatestrewrite1002_cat.xml +0 -0
- {fits2tmp-0.4.0 → fits2tmp-1.0.2}/src/fits2tmp/sofiatestrewrite100_cat.txt +0 -0
- {fits2tmp-0.4.0 → fits2tmp-1.0.2}/src/fits2tmp/sofiatestrewrite100_cat.xml +0 -0
fits2tmp-1.0.2/PKG-INFO
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fits2tmp
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: A way of loading FITS files into temporary filesystems to make them available in memory.
|
|
5
|
+
Author: Verity Allan
|
|
6
|
+
Author-email: Verity Allan <vla22@cam.ac.uk>
|
|
7
|
+
License-Expression: BSD-3-Clause
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
+
Requires-Dist: dask[distributed]>=2025.1.0,<2026
|
|
15
|
+
Requires-Dist: astropy>=6.1.4,<7
|
|
16
|
+
Requires-Dist: h5py>=3.16.0
|
|
17
|
+
Requires-Dist: numpy>=2.1.2,<3
|
|
18
|
+
Requires-Dist: pytest>=8.3.3,<9
|
|
19
|
+
Requires-Dist: zarr>=3.4.1
|
|
20
|
+
Requires-Python: >=3.12, <4
|
|
21
|
+
Project-URL: Repository, https://gitlab.developers.cam.ac.uk/phy/ra/vla22-phd/fits2tmp
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# fits2tmp
|
|
25
|
+
|
|
26
|
+
This project allows you to take a large FITS file and render it as a set of smaller FITS files stored in-memory in a temporary directory, with appropriately updated headers.
|
|
27
|
+
The program returns a list of the location of these files, which can then be processed by a parallel processing framework such as dask.
|
|
28
|
+
|
|
29
|
+
The program also allows you to turn a zarr file containing your FITS data into small FITS files, provided you have extracted the FITS file header to a text file.
|
|
30
|
+
Utilities in the program can be used to write headers out to or read them from a text file.
|
|
31
|
+
|
|
32
|
+
## TODO:
|
|
33
|
+
|
|
34
|
+
- Add a utility to convert FITS files to zarr, including saving the header out to a text file.
|
|
35
|
+
- Add hdf5 support using a similar strategy to FITS.
|
|
36
|
+
- Add xradio support.
|
|
37
|
+
|
|
38
|
+
## Installing fits2tmp
|
|
39
|
+
|
|
40
|
+
The program is available from pypi so can be installed with pip: `pip install fits2tmp`.
|
|
41
|
+
|
|
42
|
+
## Example Usage
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
import fits2tmp as f2t
|
|
46
|
+
|
|
47
|
+
a = fakefits2tmpfiles("fits", "/path/to/input/data", "/path/to/temporary/filesystem", "path/to/header/", (100, 100, 100), chunks=(20,20,20))
|
|
48
|
+
```
|
|
49
|
+
|
fits2tmp-1.0.2/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# fits2tmp
|
|
2
|
+
|
|
3
|
+
This project allows you to take a large FITS file and render it as a set of smaller FITS files stored in-memory in a temporary directory, with appropriately updated headers.
|
|
4
|
+
The program returns a list of the location of these files, which can then be processed by a parallel processing framework such as dask.
|
|
5
|
+
|
|
6
|
+
The program also allows you to turn a zarr file containing your FITS data into small FITS files, provided you have extracted the FITS file header to a text file.
|
|
7
|
+
Utilities in the program can be used to write headers out to or read them from a text file.
|
|
8
|
+
|
|
9
|
+
## TODO:
|
|
10
|
+
|
|
11
|
+
- Add a utility to convert FITS files to zarr, including saving the header out to a text file.
|
|
12
|
+
- Add hdf5 support using a similar strategy to FITS.
|
|
13
|
+
- Add xradio support.
|
|
14
|
+
|
|
15
|
+
## Installing fits2tmp
|
|
16
|
+
|
|
17
|
+
The program is available from pypi so can be installed with pip: `pip install fits2tmp`.
|
|
18
|
+
|
|
19
|
+
## Example Usage
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
import fits2tmp as f2t
|
|
23
|
+
|
|
24
|
+
a = fakefits2tmpfiles("fits", "/path/to/input/data", "/path/to/temporary/filesystem", "path/to/header/", (100, 100, 100), chunks=(20,20,20))
|
|
25
|
+
```
|
|
26
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "fits2tmp"
|
|
3
|
+
version = "1.0.2"
|
|
4
|
+
description = "A way of loading FITS files into temporary filesystems to make them available in memory."
|
|
5
|
+
requires-python = ">=3.12,<4"
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
license = "BSD-3-Clause"
|
|
8
|
+
classifiers = [
|
|
9
|
+
"Programming Language :: Python :: 3",
|
|
10
|
+
"Programming Language :: Python :: 3.10",
|
|
11
|
+
"Programming Language :: Python :: 3.11",
|
|
12
|
+
"Programming Language :: Python :: 3.12",
|
|
13
|
+
"Programming Language :: Python :: 3.13",
|
|
14
|
+
"Programming Language :: Python :: 3.14",
|
|
15
|
+
]
|
|
16
|
+
dependencies = [
|
|
17
|
+
"dask[distributed]>=2025.1.0,<2026",
|
|
18
|
+
"astropy>=6.1.4,<7",
|
|
19
|
+
"h5py>=3.16.0",
|
|
20
|
+
"numpy>=2.1.2,<3",
|
|
21
|
+
"pytest>=8.3.3,<9",
|
|
22
|
+
"zarr>=3.4.1",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[[project.authors]]
|
|
26
|
+
name = "Verity Allan"
|
|
27
|
+
email = "vla22@cam.ac.uk"
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Repository = "https://gitlab.developers.cam.ac.uk/phy/ra/vla22-phd/fits2tmp"
|
|
31
|
+
|
|
32
|
+
[build-system]
|
|
33
|
+
requires = ["uv_build>=0.13.5,<0.14.0"]
|
|
34
|
+
build-backend = "uv_build"
|
|
35
|
+
|
|
36
|
+
[tool.pytest.ini_options]
|
|
37
|
+
addopts = ["--import-mode=importlib"]
|
|
38
|
+
pythonpath = "src/fits2tmp/"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "fits2tmp"
|
|
3
|
+
version = "1.0.2"
|
|
4
|
+
description = "A way of loading FITS files into temporary filesystems to make them available in memory."
|
|
5
|
+
authors = [{ name = "Verity Allan", email = "vla22@cam.ac.uk" }]
|
|
6
|
+
requires-python = ">=3.12,<4"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
license = "BSD-3-Clause"
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Programming Language :: Python :: 3",
|
|
11
|
+
"Programming Language :: Python :: 3.10",
|
|
12
|
+
"Programming Language :: Python :: 3.11",
|
|
13
|
+
"Programming Language :: Python :: 3.12",
|
|
14
|
+
"Programming Language :: Python :: 3.13",
|
|
15
|
+
"Programming Language :: Python :: 3.14",
|
|
16
|
+
]
|
|
17
|
+
dependencies = [
|
|
18
|
+
"dask[distributed]>=2025.1.0,<2026",
|
|
19
|
+
"astropy>=6.1.4,<7",
|
|
20
|
+
"h5py>=3.16.0",
|
|
21
|
+
"numpy>=2.1.2,<3",
|
|
22
|
+
"pytest>=8.3.3,<9",
|
|
23
|
+
"zarr>=3.4.1",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Repository = "https://gitlab.developers.cam.ac.uk/phy/ra/vla22-phd/fits2tmp"
|
|
28
|
+
|
|
29
|
+
[build-system]
|
|
30
|
+
requires = ["uv_build>=0.13.5,<0.14.0"]
|
|
31
|
+
build-backend = "uv_build"
|
|
32
|
+
|
|
33
|
+
[tool.pytest.ini_options]
|
|
34
|
+
addopts = [
|
|
35
|
+
"--import-mode=importlib",
|
|
36
|
+
]
|
|
37
|
+
pythonpath = "src/fits2tmp/"
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import h5py
|
|
2
|
+
import zarr
|
|
3
|
+
import json
|
|
4
|
+
from astropy.io import fits
|
|
5
|
+
from astropy import wcs
|
|
6
|
+
import dask.array as da
|
|
7
|
+
from dask import delayed
|
|
8
|
+
from dask.distributed import Lock
|
|
9
|
+
import numpy as np
|
|
10
|
+
import os
|
|
11
|
+
import dask
|
|
12
|
+
import tempfile
|
|
13
|
+
|
|
14
|
+
def arr_size_check(source_arr, desired_arr: tuple) -> bool:
|
|
15
|
+
if len(source_arr.shape) < len(desired_arr):
|
|
16
|
+
raise ValueError("You've asked for an array with more dimensions than the array stored")
|
|
17
|
+
else:
|
|
18
|
+
for i in range(min(len(source_arr.shape), len(desired_arr))):
|
|
19
|
+
# using min here allows us to avoid an IndexError when we have more dimensions in the source array
|
|
20
|
+
j = source_arr.shape[i] - desired_arr[i]
|
|
21
|
+
if j < 0:
|
|
22
|
+
raise IndexError("Desired array size is larger than the stored array in at least position %s: source array has dimensions %s, and you have requested $s", i, source_arr.shape, desired_arr)
|
|
23
|
+
return True
|
|
24
|
+
|
|
25
|
+
#def fits_add_header(orig_header, sliced_data) -> fits.Header:
|
|
26
|
+
# coords = wcs.WCS(orig_header)
|
|
27
|
+
# new_header = orig_header
|
|
28
|
+
# new_header.update(coords[data_sli].to_header())
|
|
29
|
+
# return new_header
|
|
30
|
+
|
|
31
|
+
def header_dict(header) -> dict:
|
|
32
|
+
d = {}
|
|
33
|
+
for i in header.cards:
|
|
34
|
+
d[i.keyword] = i.value
|
|
35
|
+
return d
|
|
36
|
+
|
|
37
|
+
def dict2header(input_dict: dict) -> fits.Header:
|
|
38
|
+
nh = fits.Header(cards=input_dict)
|
|
39
|
+
return nh
|
|
40
|
+
|
|
41
|
+
def dict2file(input_dict: dict, filepath):
|
|
42
|
+
with open(filepath, 'w') as f:
|
|
43
|
+
f.write(json.dumps(input_dict))
|
|
44
|
+
|
|
45
|
+
def file2dict(input_file, filepath) -> dict:
|
|
46
|
+
with open(filepath, 'r') as j:
|
|
47
|
+
contents = json.loads(j.read())
|
|
48
|
+
return contents
|
|
49
|
+
#filepath = []
|
|
50
|
+
|
|
51
|
+
def fun(darr, destination, header, block_info=None, filepath=[]):
|
|
52
|
+
arr_loc = block_info[None]['array-location']
|
|
53
|
+
print(arr_loc)
|
|
54
|
+
ch_size = block_info[None]['chunk-shape']
|
|
55
|
+
chunk_loc = block_info[None]['chunk-location']
|
|
56
|
+
coords = []
|
|
57
|
+
for i in range(len(arr_loc)):
|
|
58
|
+
coords.append(slice(arr_loc[i][0],arr_loc[i][1]))
|
|
59
|
+
block_id = str(chunk_loc).replace(',', '-').replace('(', '-').replace(')', '').replace(' ', '')
|
|
60
|
+
n_header = dict2header(header_dict(header))
|
|
61
|
+
wcs_obj = wcs.WCS(n_header)
|
|
62
|
+
n_header.update(wcs_obj[coords].to_header())
|
|
63
|
+
out = fits.PrimaryHDU(data=darr, header=n_header)
|
|
64
|
+
outpath = destination.name + '/' + block_id + ".fits"
|
|
65
|
+
out.writeto(outpath)
|
|
66
|
+
lock = Lock()
|
|
67
|
+
with lock:
|
|
68
|
+
filepath.append(outpath)
|
|
69
|
+
return darr
|
|
70
|
+
|
|
71
|
+
def fits2tmpfiles(inputpath, destination, chunks):
|
|
72
|
+
f = fits.open(inputpath)
|
|
73
|
+
destination = tempfile.TemporaryDirectory(dir=destination, delete=False)
|
|
74
|
+
d = da.from_array(f[0].data, chunks=chunks)
|
|
75
|
+
# TODO overlap
|
|
76
|
+
de = da.overlap.overlap(d, depth=None, boundary=None)
|
|
77
|
+
da.map_blocks(fun, d, destination, f[0].header, dtype=float).compute()
|
|
78
|
+
print(filepath)
|
|
79
|
+
|
|
80
|
+
return filepath
|
|
81
|
+
|
|
82
|
+
def disk2dah(filetype, inputpath, destination, headerloc, arraysize, chunks=None):
|
|
83
|
+
# TODO: ADD code to handle arraysize differing from size of array in file
|
|
84
|
+
# maybe extend arr_size_check()?
|
|
85
|
+
# TODO make this support arrays that have other than 3 dims
|
|
86
|
+
destination = tempfile.TemporaryDirectory(dir=destination, delete=False)
|
|
87
|
+
match filetype:
|
|
88
|
+
case "fits":
|
|
89
|
+
f = fits.open(inputpath)
|
|
90
|
+
d = da.from_array(f[0].data[0:arraysize[0], 0:arraysize[1], 0:arraysize[2]], chunks=chunks)
|
|
91
|
+
n_header = dict2header(header_dict(f[0].header))
|
|
92
|
+
wcs_obj = wcs.WCS(n_header)
|
|
93
|
+
case "zarr":
|
|
94
|
+
d = da.from_zarr(inputpath, chunks=chunks)[0:arraysize, 0:arraysize[1], 0:arraysize[2]]
|
|
95
|
+
n_header = dict2header(file2dict(inputpath, headerloc))
|
|
96
|
+
wcs_obj = wcs.WCS(n_header)
|
|
97
|
+
case "hdf5":
|
|
98
|
+
f = h5py.File(filepath, "r")
|
|
99
|
+
#note this is hardcoded for the particular hdf5 files tested - needs parameterisation
|
|
100
|
+
d = da.from_array(f["array"][arraysize], chunks=chunks)
|
|
101
|
+
n_header = dict2header(file2dict(inputpath, headerloc))
|
|
102
|
+
wcs_obj = wcs.WCS(n_header)
|
|
103
|
+
|
|
104
|
+
case "xradio":
|
|
105
|
+
weeble
|
|
106
|
+
case _:
|
|
107
|
+
raise ValueError("The specified file type is not supported by fits2tmp.")
|
|
108
|
+
return [d, destination, n_header, wcs_obj]
|
|
109
|
+
|
|
110
|
+
def fakefits2tmpfiles(filetype, inputpath, destination, arraysize, headerloc=None, chunks=None, overlap=None, fpaths=[]):
|
|
111
|
+
inputarray = disk2dah(filetype, inputpath, destination, headerloc, arraysize, chunks)
|
|
112
|
+
if overlap == None:
|
|
113
|
+
overlap = [0,0,0]
|
|
114
|
+
darr = inputarray[0]
|
|
115
|
+
print(darr.shape)
|
|
116
|
+
print(darr)
|
|
117
|
+
destination = inputarray[1]
|
|
118
|
+
header = inputarray[2]
|
|
119
|
+
print(header)
|
|
120
|
+
wcs_obj = inputarray[3]
|
|
121
|
+
print(len(darr.chunks))
|
|
122
|
+
# why am I pushing this array to delayed? ans: to parallelise construction of the list
|
|
123
|
+
#dd = darr.to_delayed()
|
|
124
|
+
for i in range(len(darr.chunks[0])):
|
|
125
|
+
x = i * chunks[0] - overlap[0]
|
|
126
|
+
x_delt = (i* chunks[0]) + chunks[0] + overlap[0]
|
|
127
|
+
# range check - when asking for overlap, we curtail at the edges of the array
|
|
128
|
+
if x < 0:
|
|
129
|
+
x = 0
|
|
130
|
+
if x_delt > arraysize[0] -1:
|
|
131
|
+
x_delt = arraysize[0]
|
|
132
|
+
print(x, x_delt)
|
|
133
|
+
for j in range(len(darr.chunks[1])):
|
|
134
|
+
y = j * chunks[1] - overlap[1]
|
|
135
|
+
y_delt = (j * chunks[1]) + chunks[1] + overlap[1]
|
|
136
|
+
if y < 0:
|
|
137
|
+
y = 0
|
|
138
|
+
if y_delt > arraysize[1] -1:
|
|
139
|
+
y_delt = arraysize[1]
|
|
140
|
+
if len(darr.shape) == 2:
|
|
141
|
+
dest = str(i) + str(j)
|
|
142
|
+
data = dd[i][j]
|
|
143
|
+
wcs_coords = wcs_obj.slice((slice(x,x_delt), slice(y,y_delt)))
|
|
144
|
+
elif len(darr.shape) > 2:
|
|
145
|
+
for k in range(len(darr.chunks[2])):
|
|
146
|
+
z = k * chunks[2] - overlap[2]
|
|
147
|
+
z_delt = (k * chunks[2]) + chunks[2] + overlap[2]
|
|
148
|
+
if z < 0:
|
|
149
|
+
z = 0
|
|
150
|
+
if z_delt > arraysize[2] -1:
|
|
151
|
+
z_delt = arraysize[2]
|
|
152
|
+
data = darr[x:x_delt, y:y_delt, z:z_delt]
|
|
153
|
+
print(data.shape)
|
|
154
|
+
dest = '-' + str(i) +'-' + str(j) + '-' + str(k)
|
|
155
|
+
t = wcs_obj[x:x_delt, y:y_delt, z:z_delt]
|
|
156
|
+
header.update(t.to_header())
|
|
157
|
+
hdu = fits.PrimaryHDU(data=data.compute(), header=header)
|
|
158
|
+
hdu.writeto(destination.name + dest + "fits")
|
|
159
|
+
fpaths.append(destination.name + dest + "fits")
|
|
160
|
+
return fpaths
|
|
161
|
+
#def array2disk(array, metadata, outputtype, destination):
|
|
162
|
+
|
|
163
|
+
#def tmpfitsfile2disk(fitsfile, outputtype, destination):
|
|
164
|
+
|
|
165
|
+
#def tmpfitsfile2array(fitsfile, arraytype, arraysize, chunks=None):
|
|
166
|
+
|
|
167
|
+
#def makezarrmetadata(fitsheader):
|
|
168
|
+
|
|
169
|
+
#def makefitsmetadata(fitsheader, location):
|
|
170
|
+
|
|
171
|
+
#makehdf5metadata
|
|
172
|
+
|
|
173
|
+
#makexradiometadata
|
fits2tmp-0.4.0/LICENSE
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
BSD 3-Clause License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024, Verity Allan
|
|
4
|
-
|
|
5
|
-
Redistribution and use in source and binary forms, with or without
|
|
6
|
-
modification, are permitted provided that the following conditions are met:
|
|
7
|
-
|
|
8
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
-
list of conditions and the following disclaimer.
|
|
10
|
-
|
|
11
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
-
this list of conditions and the following disclaimer in the documentation
|
|
13
|
-
and/or other materials provided with the distribution.
|
|
14
|
-
|
|
15
|
-
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
-
contributors may be used to endorse or promote products derived from
|
|
17
|
-
this software without specific prior written permission.
|
|
18
|
-
|
|
19
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
fits2tmp-0.4.0/PKG-INFO
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: fits2tmp
|
|
3
|
-
Version: 0.4.0
|
|
4
|
-
Summary: A way of loading FITS files into temporary filesystems to make them available in memory.
|
|
5
|
-
License: BSD-3-Clause
|
|
6
|
-
Author: Verity Allan
|
|
7
|
-
Author-email: vla22@cam.ac.uk
|
|
8
|
-
Requires-Python: >=3.10,<4.0
|
|
9
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
-
Requires-Dist: aiohttp (>=3.13.3,<4.0.0)
|
|
16
|
-
Requires-Dist: astropy (>=6.1.4,<7.0.0)
|
|
17
|
-
Requires-Dist: dask[distributed] (>=2025.1.0,<2026.0.0)
|
|
18
|
-
Requires-Dist: fsspec (>=2026.2.0,<2027.0.0)
|
|
19
|
-
Requires-Dist: h5py (>=3.12.1,<4.0.0)
|
|
20
|
-
Requires-Dist: numpy (>=2.1.2,<3.0.0)
|
|
21
|
-
Requires-Dist: pytest (>=8.3.3,<9.0.0)
|
|
22
|
-
Requires-Dist: requests (>=2.32.5,<3.0.0)
|
|
23
|
-
Requires-Dist: s3fs (>=2026.2.0,<2027.0.0)
|
|
24
|
-
Requires-Dist: zarr (>=2.18.3,<3.0.0)
|
|
25
|
-
Project-URL: Repository, https://gitlab.developers.cam.ac.uk/phy/ra/vla22-phd/fits2tmp
|
|
26
|
-
Description-Content-Type: text/markdown
|
|
27
|
-
|
|
28
|
-
# fits2tmp
|
|
29
|
-
|
|
30
|
-
This project allows you to take a large FITS file and render it as a set of smaller FITS files stored in-memory in a temporary directory, with appropriately updated headers.
|
|
31
|
-
The program returns a list of the location of these files, which can then be processed, by other programs,perhaps by a parallel processing framework such as Dask, or by using Python's `subprocess` module to allow feeding those files to a non-Python program with a command line interface (CLI).
|
|
32
|
-
|
|
33
|
-
The program also allows you to turn a zarr file containing your FITS data into small FITS files, provided you have extracted the FITS file header to a text file.
|
|
34
|
-
|
|
35
|
-
This can also be done for hdf5 files (again assuming FITS file header data is saved to a text file). Note that if you attempt to do this with Dask running on multiple nodes, it will currently fail, because of a bug in Dask.
|
|
36
|
-
|
|
37
|
-
Utilities in the program can be used to write headers out to or read them from a text file.
|
|
38
|
-
|
|
39
|
-
## TODO:
|
|
40
|
-
|
|
41
|
-
- Add a utility to convert FITS files to zarr, including saving the header out to a text file.
|
|
42
|
-
- Add hdf5 support, using more native hdf5 metadata storage solutions.
|
|
43
|
-
- Add xradio/xarray support.
|
|
44
|
-
|
|
45
|
-
## Installing fits2tmp
|
|
46
|
-
|
|
47
|
-
The program is available from pypi so can be installed with pip: `pip install fits2tmp`.
|
|
48
|
-
|
|
49
|
-
## Example Usage
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
import fits2tmp as f2t
|
|
53
|
-
|
|
54
|
-
a = f2t.fitstmpfiles("fits", "/path/to/input/data", "/path/to/temporary/filesystem", "path/to/header/", (100, 100, 100), chunks=(20,20,20))
|
|
55
|
-
```
|
|
56
|
-
fitstmpfiles takes a large input data set in one of the supported formats, and returns smaller FITS files to a specified directory.
|
|
57
|
-
|
|
58
|
-
The parameters for fitstmpfiles are:
|
|
59
|
-
|
|
60
|
-
- filetype: a string describing the filetype; currently supports "fits" and "zarr" fully; "hdf5" only supported on single node runs.
|
|
61
|
-
- inputpath: path to the input data
|
|
62
|
-
- destination: path to destination directory. It is intended that temporary directories are used, to try to keep the data in-memory, rather than doing potentially expensive disk writes; however, if you wish to write to more permanent storage, that is possible. You will probably want to clean up manually once the run is done, though.
|
|
63
|
-
- headerloc: defaults to `None`. If loading from a FITS file, this isn't required; if you are loading from zarr or hdf5, you need to provide the path to a text file containing the FITS headers. It is recommended that you use the fits2tmp utilities to prepare the header file.
|
|
64
|
-
- chunks: defaults to `None`. You will want to set this to some value that makes sense for the resources on which you're processing the data. Dask recommend that you have at least 10 times as much RAM as the size of the chunk you're processing. You will also want to consider how much overlap you are using when setting the chunk size. If you are particularly concerned about file loading performance, then consider setting the chunk size to a multiple of the block size used in the storage.
|
|
65
|
-
- overlap: defaults to `None`. You will want to set this to some size that makes sense for the data processing you're doing. You probably want to set this to approximately the size of the largest Gaussian kernel you plan to use to detect objects/features.
|
|
66
|
-
|
|
67
|
-
## Utilities
|
|
68
|
-
|
|
69
|
-
These small methods are provided to make it easy to write out a FITS header to a file, to allow provision of FITS metadata when using other storage solutions.
|
|
70
|
-
To create a header from an existing FITS file:
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
from astropy.io import fits
|
|
74
|
-
import fits2tmp as f2t
|
|
75
|
-
|
|
76
|
-
with fits.open('path/to/fits/file') as f:
|
|
77
|
-
header = f[0].header
|
|
78
|
-
d = f2t.header_dict(header)
|
|
79
|
-
f2t.dict2file(d, 'path/to/where/you/save/header')
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Note that this process strips most of the history from the header; if you wish to update the history, use some of the astropy.io.fits tools to accomplish this. This tool is purely to provide a minimal amount of metadata to allow storing FITS data in zarr and similar file formats, and also to allow processing of sections of FITS files where it's not desirable to have all processes reading from the same file in storage.
|
|
83
|
-
|
|
84
|
-
To create a header from text file containing a json dump of a dictionary created from a FITS header:
|
|
85
|
-
|
|
86
|
-
```
|
|
87
|
-
import fits2tmp as ft2
|
|
88
|
-
|
|
89
|
-
loaded_header_dict = f2t.file2dict('/path/to/header/txt/file')
|
|
90
|
-
header = dict2header(loaded_header_dict)
|
|
91
|
-
```
|
|
92
|
-
This leaves you with a valid FITS header
|
|
93
|
-
|
fits2tmp-0.4.0/README.md
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# fits2tmp
|
|
2
|
-
|
|
3
|
-
This project allows you to take a large FITS file and render it as a set of smaller FITS files stored in-memory in a temporary directory, with appropriately updated headers.
|
|
4
|
-
The program returns a list of the location of these files, which can then be processed, by other programs,perhaps by a parallel processing framework such as Dask, or by using Python's `subprocess` module to allow feeding those files to a non-Python program with a command line interface (CLI).
|
|
5
|
-
|
|
6
|
-
The program also allows you to turn a zarr file containing your FITS data into small FITS files, provided you have extracted the FITS file header to a text file.
|
|
7
|
-
|
|
8
|
-
This can also be done for hdf5 files (again assuming FITS file header data is saved to a text file). Note that if you attempt to do this with Dask running on multiple nodes, it will currently fail, because of a bug in Dask.
|
|
9
|
-
|
|
10
|
-
Utilities in the program can be used to write headers out to or read them from a text file.
|
|
11
|
-
|
|
12
|
-
## TODO:
|
|
13
|
-
|
|
14
|
-
- Add a utility to convert FITS files to zarr, including saving the header out to a text file.
|
|
15
|
-
- Add hdf5 support, using more native hdf5 metadata storage solutions.
|
|
16
|
-
- Add xradio/xarray support.
|
|
17
|
-
|
|
18
|
-
## Installing fits2tmp
|
|
19
|
-
|
|
20
|
-
The program is available from pypi so can be installed with pip: `pip install fits2tmp`.
|
|
21
|
-
|
|
22
|
-
## Example Usage
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
import fits2tmp as f2t
|
|
26
|
-
|
|
27
|
-
a = f2t.fitstmpfiles("fits", "/path/to/input/data", "/path/to/temporary/filesystem", "path/to/header/", (100, 100, 100), chunks=(20,20,20))
|
|
28
|
-
```
|
|
29
|
-
fitstmpfiles takes a large input data set in one of the supported formats, and returns smaller FITS files to a specified directory.
|
|
30
|
-
|
|
31
|
-
The parameters for fitstmpfiles are:
|
|
32
|
-
|
|
33
|
-
- filetype: a string describing the filetype; currently supports "fits" and "zarr" fully; "hdf5" only supported on single node runs.
|
|
34
|
-
- inputpath: path to the input data
|
|
35
|
-
- destination: path to destination directory. It is intended that temporary directories are used, to try to keep the data in-memory, rather than doing potentially expensive disk writes; however, if you wish to write to more permanent storage, that is possible. You will probably want to clean up manually once the run is done, though.
|
|
36
|
-
- headerloc: defaults to `None`. If loading from a FITS file, this isn't required; if you are loading from zarr or hdf5, you need to provide the path to a text file containing the FITS headers. It is recommended that you use the fits2tmp utilities to prepare the header file.
|
|
37
|
-
- chunks: defaults to `None`. You will want to set this to some value that makes sense for the resources on which you're processing the data. Dask recommend that you have at least 10 times as much RAM as the size of the chunk you're processing. You will also want to consider how much overlap you are using when setting the chunk size. If you are particularly concerned about file loading performance, then consider setting the chunk size to a multiple of the block size used in the storage.
|
|
38
|
-
- overlap: defaults to `None`. You will want to set this to some size that makes sense for the data processing you're doing. You probably want to set this to approximately the size of the largest Gaussian kernel you plan to use to detect objects/features.
|
|
39
|
-
|
|
40
|
-
## Utilities
|
|
41
|
-
|
|
42
|
-
These small methods are provided to make it easy to write out a FITS header to a file, to allow provision of FITS metadata when using other storage solutions.
|
|
43
|
-
To create a header from an existing FITS file:
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
from astropy.io import fits
|
|
47
|
-
import fits2tmp as f2t
|
|
48
|
-
|
|
49
|
-
with fits.open('path/to/fits/file') as f:
|
|
50
|
-
header = f[0].header
|
|
51
|
-
d = f2t.header_dict(header)
|
|
52
|
-
f2t.dict2file(d, 'path/to/where/you/save/header')
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Note that this process strips most of the history from the header; if you wish to update the history, use some of the astropy.io.fits tools to accomplish this. This tool is purely to provide a minimal amount of metadata to allow storing FITS data in zarr and similar file formats, and also to allow processing of sections of FITS files where it's not desirable to have all processes reading from the same file in storage.
|
|
56
|
-
|
|
57
|
-
To create a header from text file containing a json dump of a dictionary created from a FITS header:
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
import fits2tmp as ft2
|
|
61
|
-
|
|
62
|
-
loaded_header_dict = f2t.file2dict('/path/to/header/txt/file')
|
|
63
|
-
header = dict2header(loaded_header_dict)
|
|
64
|
-
```
|
|
65
|
-
This leaves you with a valid FITS header
|
fits2tmp-0.4.0/pyproject.toml
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
[tool.poetry]
|
|
2
|
-
name = "fits2tmp"
|
|
3
|
-
version = "0.4.0"
|
|
4
|
-
description = "A way of loading FITS files into temporary filesystems to make them available in memory."
|
|
5
|
-
license = "BSD-3-Clause"
|
|
6
|
-
authors = ["Verity Allan <vla22@cam.ac.uk>"]
|
|
7
|
-
readme = "README.md"
|
|
8
|
-
repository = "https://gitlab.developers.cam.ac.uk/phy/ra/vla22-phd/fits2tmp"
|
|
9
|
-
|
|
10
|
-
[tool.poetry.dependencies]
|
|
11
|
-
python = "^3.10"
|
|
12
|
-
dask = {extras = ["distributed"], version = "^2025.1.0"}
|
|
13
|
-
astropy = "^6.1.4"
|
|
14
|
-
h5py = "^3.12.1"
|
|
15
|
-
numpy = "^2.1.2"
|
|
16
|
-
pytest = "^8.3.3"
|
|
17
|
-
zarr = "^2.18.3"
|
|
18
|
-
fsspec = "^2026.2.0"
|
|
19
|
-
requests = "^2.32.5"
|
|
20
|
-
aiohttp = "^3.13.3"
|
|
21
|
-
s3fs = "^2026.2.0"
|
|
22
|
-
|
|
23
|
-
[tool.pytest.ini_options]
|
|
24
|
-
addopts = [
|
|
25
|
-
"--import-mode=importlib",
|
|
26
|
-
]
|
|
27
|
-
pythonpath = "src/fits2tmp/"
|
|
28
|
-
|
|
29
|
-
[build-system]
|
|
30
|
-
requires = ["poetry-core"]
|
|
31
|
-
build-backend = "poetry.core.masonry.api"
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import h5py
|
|
2
|
-
import zarr
|
|
3
|
-
import json
|
|
4
|
-
from astropy.io import fits
|
|
5
|
-
from astropy import wcs
|
|
6
|
-
import dask.array as da
|
|
7
|
-
from dask import delayed
|
|
8
|
-
from dask.distributed import Lock
|
|
9
|
-
import numpy as np
|
|
10
|
-
import os
|
|
11
|
-
import dask
|
|
12
|
-
import tempfile
|
|
13
|
-
|
|
14
|
-
def arr_size_check(source_arr, desired_arr: tuple) -> bool:
|
|
15
|
-
if len(source_arr.shape) < len(desired_arr):
|
|
16
|
-
raise ValueError("You've asked for an array with more dimensions than the array stored")
|
|
17
|
-
else:
|
|
18
|
-
for i in range(min(len(source_arr.shape), len(desired_arr))):
|
|
19
|
-
# using min here allows us to avoid an IndexError when we have more dimensions in the source array
|
|
20
|
-
j = source_arr.shape[i] - desired_arr[i]
|
|
21
|
-
if j < 0:
|
|
22
|
-
raise IndexError("Desired array size is larger than the stored array in at least position %s: source array has dimensions %s, and you have requested $s", i, source_arr.shape, desired_arr)
|
|
23
|
-
return True
|
|
24
|
-
|
|
25
|
-
#def fits_add_header(orig_header, sliced_data) -> fits.Header:
|
|
26
|
-
# coords = wcs.WCS(orig_header)
|
|
27
|
-
# new_header = orig_header
|
|
28
|
-
# new_header.update(coords[data_sli].to_header())
|
|
29
|
-
# return new_header
|
|
30
|
-
|
|
31
|
-
def header_dict(header) -> dict:
|
|
32
|
-
d = {}
|
|
33
|
-
for i in header.cards:
|
|
34
|
-
d[i.keyword] = i.value
|
|
35
|
-
return d
|
|
36
|
-
|
|
37
|
-
def dict2header(input_dict: dict) -> fits.Header:
|
|
38
|
-
nh = fits.Header(cards=input_dict)
|
|
39
|
-
return nh
|
|
40
|
-
|
|
41
|
-
def dict2file(input_dict: dict, filepath):
|
|
42
|
-
with open(filepath, 'w') as f:
|
|
43
|
-
f.write(json.dumps(input_dict))
|
|
44
|
-
|
|
45
|
-
def file2dict(filepath) -> dict:
|
|
46
|
-
with open(filepath, 'r') as j:
|
|
47
|
-
contents = json.loads(j.read())
|
|
48
|
-
return contents
|
|
49
|
-
filepath = []
|
|
50
|
-
|
|
51
|
-
def disk2dah(filetype, inputpath, destination, headerloc, arraysize, chunks=None, use_fsspec=False, storage_opts=None):
|
|
52
|
-
# TODO: ADD code to handle arraysize differing from size of array in file
|
|
53
|
-
# maybe extend arr_size_check()?
|
|
54
|
-
# TODO make this support arrays that have other than 3 dims
|
|
55
|
-
destination = tempfile.TemporaryDirectory(dir=destination, delete=False)
|
|
56
|
-
match filetype:
|
|
57
|
-
case "fits":
|
|
58
|
-
with fits.open(inputpath, use_fsspec=use_fsspec, fsspec_kwargs=storage_opts) as f:
|
|
59
|
-
match len(arraysize):
|
|
60
|
-
case 1:
|
|
61
|
-
if len(arraysize) == len(f[0].data.shape):
|
|
62
|
-
d = da.from_array(f[0].data[0:arraysize[0]], chunks=chunks)
|
|
63
|
-
elif len(arraysize) == len(f[0].data.shape) - 1:
|
|
64
|
-
d = da.from_array(f[0].data[0:arraysize[0],0], chunks=chunks)
|
|
65
|
-
elif len(arraysize) == len(f[0].data.shape) -2:
|
|
66
|
-
d = da.from_array(f[0].data[0:arraysize[0],0,0], chunks=chunks)
|
|
67
|
-
elif len(arraysize) == len(f[0].data.shape) -3:
|
|
68
|
-
d = da.from_array(f[0].data[0:arraysize[0],0,0,0], chunks=chunks)
|
|
69
|
-
else:
|
|
70
|
-
raise ValueError("You've asked to load an array with more than 4 dimensions, which is not supported.")
|
|
71
|
-
|
|
72
|
-
case 2:
|
|
73
|
-
if len(arraysize) == len(f[0].data.shape):
|
|
74
|
-
d = da.from_array(f[0].data[0:arraysize[0], 0:arraysize[1]], chunks=chunks)
|
|
75
|
-
elif len(arraysize) == len(f[0].data.shape) - 1:
|
|
76
|
-
d = da.from_array(f[0].data[0:arraysize[0],0:arraysize[1], 0], chunks=chunks)
|
|
77
|
-
elif len(arraysize) == len(f[0].data.shape) -2:
|
|
78
|
-
d = da.from_array(f[0].data[0:arraysize[0],0:arraysize[1],0,0], chunks=chunks)
|
|
79
|
-
else:
|
|
80
|
-
raise ValueError("You've asked to load an array with more than 4 dimensions, which is not supported.")
|
|
81
|
-
case 3:
|
|
82
|
-
if len(arraysize) == len(f[0].data.shape):
|
|
83
|
-
d = da.from_array(f[0].data[0:arraysize[0], 0:arraysize[1], 0:arraysize[2]], chunks=chunks)
|
|
84
|
-
elif len(arraysize) == len(f[0].data.shape) - 1:
|
|
85
|
-
d = da.from_array(f[0].data[0:arraysize[0],0:arrasize[1], 0:arraysize[2],0], chunks=chunks)
|
|
86
|
-
else:
|
|
87
|
-
raise ValueError("You've asked to load an array with more than 4 dimensions, which is not supported.")
|
|
88
|
-
case 4:
|
|
89
|
-
d = da.from_array(f[0].data[0:arraysize[0], 0:arraysize[1], 0:arraysize[2], 0:arraysize[3]], chunks=chunks)
|
|
90
|
-
n_header = dict2header(header_dict(f[0].header))
|
|
91
|
-
wcs_obj = wcs.WCS(n_header)
|
|
92
|
-
case "zarr":
|
|
93
|
-
if use_fsspec == True:
|
|
94
|
-
d = da.from_zarr(inputpath, storage_options=storage_opts, chunks=chunks)[0:arraysize[0],0:arraysize[1],0:arraysize[2]]
|
|
95
|
-
print(type(d))
|
|
96
|
-
else:
|
|
97
|
-
d = da.from_zarr(inputpath, chunks=chunks)[0:arraysize[0],0:arraysize[1],0:arraysize[2]]
|
|
98
|
-
n_header = dict2header(file2dict(headerloc))
|
|
99
|
-
wcs_obj = wcs.WCS(n_header)
|
|
100
|
-
case "hdf5":
|
|
101
|
-
with h5py.File(filepath, "r") as f:
|
|
102
|
-
#note this is hardcoded for the particular hdf5 files tested - needs parameterisation
|
|
103
|
-
d = da.from_array(f["array"][arraysize], chunks=chunks)
|
|
104
|
-
n_header = dict2header(file2dict(inputpath, headerloc))
|
|
105
|
-
wcs_obj = wcs.WCS(n_header)
|
|
106
|
-
|
|
107
|
-
case "xradio":
|
|
108
|
-
weeble
|
|
109
|
-
case _:
|
|
110
|
-
raise ValueError("The specified file type is not supported by fits2tmp.")
|
|
111
|
-
return [d, destination, n_header, wcs_obj]
|
|
112
|
-
|
|
113
|
-
def fitstmpfiles(filetype, inputpath, destination, arraysize, headerloc=None, chunks=None, overlap=None):
|
|
114
|
-
inputarray = disk2dah(filetype, inputpath, destination, headerloc, arraysize, chunks)
|
|
115
|
-
if overlap == None:
|
|
116
|
-
overlap = [0,0,0]
|
|
117
|
-
darr = inputarray[0]
|
|
118
|
-
destination = inputarray[1]
|
|
119
|
-
header = inputarray[2]
|
|
120
|
-
wcs_obj = inputarray[3]
|
|
121
|
-
# why am I pushing this array to delayed? ans: to parallelise construction of the list
|
|
122
|
-
#dd = darr.to_delayed()
|
|
123
|
-
fpaths = []
|
|
124
|
-
data = []
|
|
125
|
-
for i in range(len(darr.chunks[0])):
|
|
126
|
-
x = i * chunks[0] - overlap[0]
|
|
127
|
-
x_delt = (i* chunks[0]) + chunks[0] + overlap[0]
|
|
128
|
-
# range check - when asking for overlap, we curtail at the edges of the array
|
|
129
|
-
if x < 0:
|
|
130
|
-
x = 0
|
|
131
|
-
if x_delt > arraysize[0] -1:
|
|
132
|
-
x_delt = arraysize[0]
|
|
133
|
-
if len(darr.shape) == 1:
|
|
134
|
-
#can't think of why we want to support 1D array stuff, but it's probably OK to do this, though the headers will end up not very useful, probably
|
|
135
|
-
dest = str(i)
|
|
136
|
-
data = darr[x:x_delt]
|
|
137
|
-
t = wcs_obj[x:x_delt]
|
|
138
|
-
header.update(t.to_header())
|
|
139
|
-
hdu = fits.PrimaryHDU(data=data, header=header)
|
|
140
|
-
hdu.writeto(destination.name + dest + "fits")
|
|
141
|
-
fpaths.append(destination.name + dest + "fits")
|
|
142
|
-
else:
|
|
143
|
-
for j in range(len(darr.chunks[1])):
|
|
144
|
-
y = j * chunks[1] - overlap[1]
|
|
145
|
-
y_delt = (j * chunks[1]) + chunks[1] + overlap[1]
|
|
146
|
-
if y < 0:
|
|
147
|
-
y = 0
|
|
148
|
-
if y_delt > arraysize[1] -1:
|
|
149
|
-
y_delt = arraysize[1]
|
|
150
|
-
if len(darr.shape) == 2:
|
|
151
|
-
dest = str(i) + str(j)
|
|
152
|
-
data = darr[x:x_delt, y:y_delt]
|
|
153
|
-
t = wcs_obj[x:x_delt, y:y_delt]
|
|
154
|
-
header.update(t.to_header())
|
|
155
|
-
hdu = fits.PrimaryHDU(data=data, header=header)
|
|
156
|
-
hdu.writeto(destination.name + dest + "fits")
|
|
157
|
-
fpaths.append(destination.name + dest + "fits")
|
|
158
|
-
elif len(darr.shape) > 2:
|
|
159
|
-
for k in range(len(darr.chunks[2])):
|
|
160
|
-
z = k * chunks[2] - overlap[2]
|
|
161
|
-
z_delt = (k * chunks[2]) + chunks[2] + overlap[2]
|
|
162
|
-
if z < 0:
|
|
163
|
-
z = 0
|
|
164
|
-
if z_delt > arraysize[2] -1:
|
|
165
|
-
z_delt = arraysize[2]
|
|
166
|
-
dest = '-' + str(i) +'-' + str(j) + '-' + str(k)
|
|
167
|
-
if len(darr.shape) == 3:
|
|
168
|
-
data = darr[x:x_delt, y:y_delt, z:z_delt]
|
|
169
|
-
t = wcs_obj[x:x_delt, y:y_delt, z:z_delt]
|
|
170
|
-
header.update(t.to_header())
|
|
171
|
-
elif len(darr.shape) == 4:
|
|
172
|
-
# this assumes we're dealing with radio astronomy data, so we just select all indices in the 4th axis, which is usually polarisation information
|
|
173
|
-
data = darr[x:x_delt, y:y_delt, z:z_delt, :]
|
|
174
|
-
t = wcs_obj[x:x_delt, y:y_delt, z:z_delt, :]
|
|
175
|
-
header.update(t.to_header())
|
|
176
|
-
hdu = fits.PrimaryHDU(data=data, header=header)
|
|
177
|
-
hdu.writeto(destination.name + dest + "fits")
|
|
178
|
-
fpaths.append(destination.name + dest + "fits")
|
|
179
|
-
return fpaths
|
|
180
|
-
#def array2disk(array, metadata, outputtype, destination):
|
|
181
|
-
|
|
182
|
-
#def tmpfitsfile2disk(fitsfile, outputtype, destination):
|
|
183
|
-
|
|
184
|
-
#def tmpfitsfile2array(fitsfile, arraytype, arraysize, chunks=None):
|
|
185
|
-
|
|
186
|
-
#def makezarrmetadata(fitsheader):
|
|
187
|
-
|
|
188
|
-
#def makefitsmetadata(fitsheader, location):
|
|
189
|
-
|
|
190
|
-
#makehdf5metadata
|
|
191
|
-
|
|
192
|
-
#makexradiometadata
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|