plotastrodata 1.7.13__tar.gz → 1.7.14__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.
Files changed (24) hide show
  1. {plotastrodata-1.7.13/plotastrodata.egg-info → plotastrodata-1.7.14}/PKG-INFO +1 -1
  2. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/__init__.py +1 -1
  3. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/other_utils.py +100 -101
  4. {plotastrodata-1.7.13 → plotastrodata-1.7.14/plotastrodata.egg-info}/PKG-INFO +1 -1
  5. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/LICENSE +0 -0
  6. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/MANIFEST.in +0 -0
  7. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/README.md +0 -0
  8. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/analysis_utils.py +0 -0
  9. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/const_utils.py +0 -0
  10. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/coord_utils.py +0 -0
  11. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/ext_utils.py +0 -0
  12. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/fft_utils.py +0 -0
  13. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/fits_utils.py +0 -0
  14. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/fitting_utils.py +0 -0
  15. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/los_utils.py +0 -0
  16. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/matrix_utils.py +0 -0
  17. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata/plot_utils.py +0 -0
  18. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata.egg-info/SOURCES.txt +0 -0
  19. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata.egg-info/dependency_links.txt +0 -0
  20. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata.egg-info/not-zip-safe +0 -0
  21. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata.egg-info/requires.txt +0 -0
  22. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/plotastrodata.egg-info/top_level.txt +0 -0
  23. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/setup.cfg +0 -0
  24. {plotastrodata-1.7.13 → plotastrodata-1.7.14}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.7.13
3
+ Version: 1.7.14
4
4
  Summary: plotastrodata is a tool for astronomers to create figures from FITS files and perform fundamental data analyses with ease.
5
5
  Home-page: https://github.com/yusukeaso-astron/plotastrodata
6
6
  Download-URL: https://github.com/yusukeaso-astron/plotastrodata
@@ -1,4 +1,4 @@
1
1
  import warnings
2
2
 
3
3
  warnings.simplefilter('ignore', FutureWarning)
4
- __version__ = '1.7.13'
4
+ __version__ = '1.7.14'
@@ -37,125 +37,124 @@ def isdeg(s: str) -> bool:
37
37
  return False
38
38
 
39
39
 
40
+ def _estimate_rms_hist(data: np.ndarray, sigma: str) -> tuple:
41
+ h_range = (-3.5, 3.5)
42
+ h = np.linspace(*h_range, 101)
43
+ dh = 0.07
44
+ m0 = np.mean(data)
45
+ s0 = np.std(data)
46
+ hist, hbin = np.histogram((data - m0) / s0, bins=100,
47
+ density=True, range=h_range)
48
+ hbin = (hbin[:-1] + hbin[1:]) / 2
49
+
50
+ def normalize(f):
51
+ """Decorator to normalize a function over h_range."""
52
+ def wrapper(x, *args):
53
+ area = np.sum(f(h, *args)) * dh
54
+ if area == 0:
55
+ p = np.where(np.abs(x - args[1]) < dh / 2, 1 / dh, 0)
56
+ else:
57
+ p = f(x, *args) / area
58
+ return p
59
+ return wrapper
60
+
61
+ if 'pbcor' in sigma:
62
+ @normalize
63
+ def model(x, *args):
64
+ s, m, R = args
65
+ x1 = (x - m) / np.sqrt(2) / s
66
+ x0 = (x * 2**(-R**2) - m) / np.sqrt(2) / s
67
+ p = erf(x1) - erf(x0)
68
+ p = p / (2 * np.log(2) * x * R**2)
69
+ return p
70
+ bounds = [[0.1, 2], [-2, 2], [0.1, 2]]
71
+ else:
72
+ @normalize
73
+ def model(x, *args):
74
+ s, m = args
75
+ x1 = (x - m) / np.sqrt(2) / s
76
+ p = np.exp(-x1**2)
77
+ p = p / (np.sqrt(2 * np.pi) * s)
78
+ return p
79
+ bounds = [[0.1, 2], [-2, 2]]
80
+ # curve_fit does not work for this fitting.
81
+ fitter = EmceeCorner(bounds=bounds, sigma=np.max(hist) * 0.01,
82
+ model=model, xdata=hbin, ydata=hist)
83
+ fitter.fit(nwalkersperdim=4, nsteps=200, nburnin=0)
84
+ popt = fitter.popt
85
+ ave = popt[1] * s0 + m0
86
+ noise = popt[0] * s0
87
+ return ave, noise
88
+
89
+
40
90
  def estimate_rms(data: np.ndarray, sigma: float | str | None = 'hist'
41
91
  ) -> float:
42
92
  """Estimate a noise level of a N-D array.
43
93
  When a float number or None is given, this function just outputs it.
44
- Following methos are acceptable.
94
+ The following methods are acceptable for data selection. Multiple options are possible.
45
95
  'edge': use data[0] and data[-1].
96
+ 'out': exclude inner 60% about axes=-2 and -1.
46
97
  'neg': use only negative values.
47
- 'med': use the median of data^2 assuming Gaussian.
48
98
  'iter': exclude outliers.
49
- 'out': exclude inner 60% about axes=-2 and -1.
50
- 'hist': fit histgram with Gaussian. This option can be combined with 'edge' and/or 'neg'.
51
- 'hist-pbcor': fit histgram with PB-corrected Gaussian. This option can be combined with 'edge' and/or 'neg'.
99
+ The following methods are acceptable for noise estimation. Only single option is possible.
100
+ 'med': calculate rms from the median of data^2 assuming Gaussian.
101
+ 'hist': fit histgram with Gaussian.
102
+ 'hist-pbcor': fit histgram with PB-corrected Gaussian.
103
+ '(no string)': calculate the mean and standard deviation.
52
104
 
53
105
  Args:
54
106
  data (np.ndarray): N-D array.
55
- sigma (float or str): One of the methods above. Defaults to 'hist'.
107
+ sigma (float or str): Methods above, like 'edge,neg,hist-pbcor'. Defaults to 'hist'.
56
108
 
57
109
  Returns:
58
- float: the estimated standard deviation of noise.
110
+ float: The estimated standard deviation of noise.
59
111
  """
60
- if sigma is None:
61
- return None
62
-
63
- def warning_offset(ave, noise):
64
- if np.abs(ave) > 0.2 * noise:
65
- s = 'The intensity offset is larger than 0.2 sigma.'
66
- warnings.warn(s, UserWarning)
67
-
68
112
  nums = [float, int, np.float64, np.int64, np.float32, np.int32]
69
- if type(sigma) in nums:
70
- noise = sigma
71
- elif np.ndim(np.squeeze(data)) == 0:
113
+ if sigma is None or type(sigma) in nums:
114
+ return sigma
115
+
116
+ if np.ndim(np.squeeze(data)) == 0:
72
117
  print('sigma cannot be estimated from only one pixel.')
73
- noise = 0.0
74
- elif sigma == 'edge':
75
- ave = np.nanmean(data[::len(data) - 1])
76
- noise = np.nanstd(data[::len(data) - 1])
77
- warning_offset(ave, noise)
78
- elif sigma == 'neg':
79
- noise = np.sqrt(np.nanmean(data[data < 0]**2))
80
- elif sigma == 'med':
81
- noise = np.sqrt(np.nanmedian(data**2) / 0.454936)
82
- elif sigma == 'iter':
83
- n = data.copy()
84
- for _ in range(5):
85
- ave, sig = np.nanmean(n), np.nanstd(n)
86
- n = n - ave
87
- n = n[np.abs(n) < 3.5 * sig]
88
- ave = np.nanmean(n)
89
- noise = np.nanstd(n)
90
- warning_offset(ave, noise)
91
- elif sigma == 'out':
92
- n, n0, n1 = data * 1, len(data), len(data[0])
93
- n = np.moveaxis(n, [-2, -1], [0, 1])
94
- n[n0//5: n0*4//5, n1//5: n1*4//5] = np.nan
95
- if np.all(np.isnan(n)):
96
- print('sigma=\'neg\' instead of \'out\' because'
97
- + ' the outer region is filled with nan.')
98
- noise = np.sqrt(np.nanmean(data[data < 0]**2))
118
+ return 0.0
119
+
120
+ # Selection
121
+ n = data * 1
122
+ if 'edge' in sigma:
123
+ if np.ndim(n) <= 2:
124
+ print('\'edge\' is ignored because ndim <= 2.')
99
125
  else:
100
- ave = np.nanmean(n)
101
- noise = np.nanstd(n)
102
- warning_offset(ave, noise)
103
- elif 'hist' in sigma:
104
- n = data * 1
105
- if 'edge' in sigma:
106
126
  n = n[::len(n) - 1]
107
- if 'neg' in sigma:
108
- n = n[n < 0]
109
- n = np.r_[n, -n]
110
- n = n[~np.isnan(n)]
111
- m0, s0 = np.mean(n), np.std(n)
112
- hist, hbin = np.histogram((n - m0) / s0,
113
- bins=100, density=True,
114
- range=(-3.5, 3.5))
115
- hbin = (hbin[:-1] + hbin[1:]) / 2
116
- h = np.linspace(-3.5, 3.5, 101)
117
- dh = 0.07
118
-
119
- def normalize(f, x, *args):
120
- # For normalization within (-3.5, 3.5), not (-inf, inf).
121
- area = np.sum(f(h, *args)) * dh
122
- if area == 0:
123
- p = np.where(np.abs(x - args[1]) < dh / 2, 1 / dh, 0)
124
- else:
125
- p = f(x, *args) / area
126
- return p
127
-
128
- if 'pbcor' in sigma:
129
- bounds = [[0.1, 2], [-2, 2], [0.1, 2]]
130
-
131
- def g(x, *p):
132
- s, m, R = p
133
- x1 = (x - m) / np.sqrt(2) / s
134
- x0 = (x * 2**(-R**2) - m) / np.sqrt(2) / s
135
- p = erf(x1) - erf(x0)
136
- p = p / (2 * np.log(2) * x * R**2)
137
- return p
127
+ if 'out' in sigma and 'pbcor' in sigma:
128
+ print('\'out\' is ignored because of \'pbcor\'.')
129
+ elif 'out' in sigma:
130
+ nx = np.shape(n)[-1]
131
+ ny = np.shape(n)[-2]
132
+ ntmp = np.moveaxis(n, [-2, -1], [0, 1])
133
+ ntmp[ny // 5 : ny * 4 // 5, nx // 5 : nx * 4 // 5] = np.nan
134
+ if np.all(np.isnan(ntmp)):
135
+ print('\'out\' is ignored because'
136
+ + ' the outer region is filled with nan.')
138
137
  else:
139
- bounds = [[0.1, 2], [-2, 2]]
140
-
141
- def g(x, *p):
142
- s, m = p
143
- x1 = (x - m) / np.sqrt(2) / s
144
- p = np.exp(-x1**2)
145
- p = p / (np.sqrt(2 * np.pi) * s)
146
- return p
147
-
148
- def model(x, *p):
149
- return normalize(g, x, *p)
150
- # curve_fit does not work for this fitting.
151
- fitter = EmceeCorner(bounds=bounds, model=model,
152
- xdata=hbin, ydata=hist,
153
- sigma=np.max(hist) * 0.01)
154
- fitter.fit(nwalkersperdim=4, nsteps=200, nburnin=0)
155
- popt = fitter.popt
156
- ave = popt[1] * s0 + m0
157
- noise = popt[0] * s0
158
- warning_offset(ave, noise)
138
+ n = ntmp
139
+ n = n[~np.isnan(n)]
140
+ if 'neg' in sigma:
141
+ n = n[n < 0]
142
+ n = np.r_[n, -n]
143
+ if 'iter' in sigma:
144
+ for _ in range(5):
145
+ n = n[np.abs(n - np.mean(n)) < 3.5 * np.std(n)]
146
+ # Estimation
147
+ if 'hist' in sigma:
148
+ ave, noise = _estimate_rms_hist(n, sigma)
149
+ elif 'med' in sigma:
150
+ ave = 0
151
+ noise = np.sqrt(np.median(n**2) / 0.454936)
152
+ else:
153
+ ave = np.mean(n)
154
+ noise = np.std(n)
155
+ if np.abs(ave) > 0.2 * noise:
156
+ s = 'The intensity offset is larger than 0.2 sigma.'
157
+ warnings.warn(s, UserWarning)
159
158
  return noise
160
159
 
161
160
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.7.13
3
+ Version: 1.7.14
4
4
  Summary: plotastrodata is a tool for astronomers to create figures from FITS files and perform fundamental data analyses with ease.
5
5
  Home-page: https://github.com/yusukeaso-astron/plotastrodata
6
6
  Download-URL: https://github.com/yusukeaso-astron/plotastrodata
File without changes
File without changes
File without changes
File without changes