plotastrodata 1.8.5__tar.gz → 1.8.7__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 (25) hide show
  1. {plotastrodata-1.8.5/plotastrodata.egg-info → plotastrodata-1.8.7}/PKG-INFO +1 -1
  2. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/__init__.py +1 -1
  3. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/analysis_utils.py +6 -2
  4. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/plot_utils.py +117 -73
  5. {plotastrodata-1.8.5 → plotastrodata-1.8.7/plotastrodata.egg-info}/PKG-INFO +1 -1
  6. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/LICENSE +0 -0
  7. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/MANIFEST.in +0 -0
  8. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/README.md +0 -0
  9. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/const_utils.py +0 -0
  10. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/coord_utils.py +0 -0
  11. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/ext_utils.py +0 -0
  12. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/fft_utils.py +0 -0
  13. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/fits_utils.py +0 -0
  14. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/fitting_utils.py +0 -0
  15. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/los_utils.py +0 -0
  16. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/matrix_utils.py +0 -0
  17. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/noise_utils.py +0 -0
  18. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata/other_utils.py +0 -0
  19. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata.egg-info/SOURCES.txt +0 -0
  20. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata.egg-info/dependency_links.txt +0 -0
  21. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata.egg-info/not-zip-safe +0 -0
  22. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata.egg-info/requires.txt +0 -0
  23. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/plotastrodata.egg-info/top_level.txt +0 -0
  24. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/setup.cfg +0 -0
  25. {plotastrodata-1.8.5 → plotastrodata-1.8.7}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.8.5
3
+ Version: 1.8.7
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.8.5'
4
+ __version__ = '1.8.7'
@@ -155,6 +155,12 @@ class AstroData():
155
155
  ws = ', '.join([f'{s:d}' for s in w[1:]])
156
156
  print(f'width was changed to [{ws}].')
157
157
  newsize = size // w
158
+ if w[1] > 1:
159
+ print(f'sigma has been divided by sqrt({w[1]:d})'
160
+ + ' because of binning in the v-axis.')
161
+ self.sigma = self.sigma / np.sqrt(w[1])
162
+ if w[2] > 1 or w[3] > 1:
163
+ print('Binning in the x- or y-axis does not update sigma.')
158
164
  grid = [None, self.v, self.y, self.x]
159
165
  dgrid = [None, self.dv, self.dy, self.dx]
160
166
  for n in range(1, 4):
@@ -181,8 +187,6 @@ class AstroData():
181
187
  self.data = np.squeeze(d)
182
188
  _, self.v, self.y, self.x = grid
183
189
  _, self.dv, self.dy, self.dx = dgrid
184
- s = 'AstroData.sigma is not updated by AstroData.binning().'
185
- warnings.warn(s, UserWarning)
186
190
 
187
191
  def centering(self, includexy: bool = True,
188
192
  includev: bool = False,
@@ -65,7 +65,17 @@ def logticks(ticks: list[float], lim: list[float, float]
65
65
  return newticks, newlabels
66
66
 
67
67
 
68
- def logcbticks(vmin: float, vmax: float):
68
+ def logcbticks(vmin: float = -3.01, vmax: float = 3.01
69
+ ) -> tuple[np.ndarray, np.ndarray]:
70
+ """Make nice ticks for a log color bar.
71
+
72
+ Args:
73
+ vmin (float, optional): Minimum value. Defaults to -3.01.
74
+ vmax (float, optional): Maximum value. Defaults to 3.01.
75
+
76
+ Returns:
77
+ tuple: (ticks, ticklabels).
78
+ """
69
79
  ticks = np.outer(np.logspace(-3, 3, 7), np.arange(1, 10))
70
80
  ticklabels = []
71
81
  for i in range(-3, 4):
@@ -85,6 +95,68 @@ def logcbticks(vmin: float, vmax: float):
85
95
  return ticks, ticklabels
86
96
 
87
97
 
98
+ def pow10(x: np.ndarray, stretchpower: float, xmin: float
99
+ ) -> np.ndarray:
100
+ """A power-law function scaled by xmin. This function is used for the case of stretch='power' in PlotAstroData.add_color().
101
+
102
+ Args:
103
+ x (np.ndarray): Input in the linear scale.
104
+ stretchpower (float): Power-law index between 0 and 1. 0 means the linear scale, while 1 means the logarithmic scale.
105
+ stretchscale (float): The minimum value of x. xmin must be positive.
106
+
107
+ Returns:
108
+ np.ndarray: Output values.
109
+ """
110
+ p = 1 - stretchpower
111
+ y = ((x / xmin)**p - 1) / p / np.log(10)
112
+ return y
113
+
114
+
115
+ def ipow10(x: np.ndarray, stretchpower: float, xmin: float
116
+ ) -> np.ndarray:
117
+ """The inverse function of pow10. This function is used for the case of stretch='power' in PlotAstroData.add_color().
118
+
119
+ Args:
120
+ x (np.ndarray): Input values.
121
+ stretchpower (float): Power-law index between 0 and 1. 0 means the linear scale, while 1 means the logarithmic scale.
122
+ xmin (float): The minimum value of x. xmin must be positive.
123
+
124
+ Returns:
125
+ np.ndarray: Output values in the linear scale.
126
+ """
127
+ p = 1 - stretchpower
128
+ y = xmin * (1 + p * np.log(10) * x)**(1 / p)
129
+ return y
130
+
131
+
132
+ def _func_stretch(x: list | np.ndarray,
133
+ stretch: str, stretchscale: float,
134
+ stretchpower: float, minlinear: float):
135
+ t = np.array(x)
136
+ match stretch:
137
+ case 'log':
138
+ t = np.log10(t)
139
+ case 'asinh':
140
+ t = np.arcsinh(t / stretchscale)
141
+ case 'power':
142
+ t = pow10(t, stretchpower, minlinear)
143
+ return t
144
+
145
+
146
+ def _ifunc_stretch(x: object,
147
+ stretch: str, stretchscale: float,
148
+ stretchpower: float, minlinear: float):
149
+ t = np.array(x)
150
+ match stretch:
151
+ case 'log':
152
+ t = 10**t
153
+ case 'asinh':
154
+ t = np.sinh(t) * stretchscale
155
+ case 'power':
156
+ t = ipow10(t, stretchpower, minlinear)
157
+ return t
158
+
159
+
88
160
  @dataclass
89
161
  class PlotAxes2D():
90
162
  """Use Axes.set_* to adjust x and y axes.
@@ -189,7 +261,7 @@ class PlotAxes2D():
189
261
 
190
262
 
191
263
  def set_minmax(data: np.ndarray, stretch: str, stretchscale: float,
192
- stretchpower: float, rms: float, kw: dict
264
+ stretchpower: float, sigma: float, kw: dict
193
265
  ) -> np.ndarray:
194
266
  """Set vmin and vmax for color pcolormesh and RGB maps.
195
267
 
@@ -198,7 +270,7 @@ def set_minmax(data: np.ndarray, stretch: str, stretchscale: float,
198
270
  stretch (str): 'log', 'asinh', 'power'. Any other means linear.
199
271
  stretchscale (float): For the arcsinh strech.
200
272
  stretchpower (float): For the power strech.
201
- rms (float): RMS noise level.
273
+ sigma (float): Noise level.
202
274
  kw (dict): Probably like {'vmin':0, 'vmax':1}.
203
275
 
204
276
  Returns:
@@ -206,46 +278,38 @@ def set_minmax(data: np.ndarray, stretch: str, stretchscale: float,
206
278
  """
207
279
  if type(stretch) is str:
208
280
  data = [data]
209
- rms = [rms]
281
+ sigma = [sigma]
210
282
  stretch = [stretch]
211
283
  stretchscale = [stretchscale]
284
+ stretchpower = [stretchpower]
212
285
  if 'vmin' in kw:
213
286
  kw['vmin'] = [kw['vmin']]
214
287
  if 'vmax' in kw:
215
288
  kw['vmax'] = [kw['vmax']]
216
- z = (data, stretch, stretchscale, rms)
217
- for i, (c, st, stsc, r) in enumerate(zip(*z)):
218
- if stsc is None:
219
- stsc = r
220
- if st == 'log':
221
- if np.any(c > 0):
222
- c = np.log10(c.clip(np.nanmin(c[c > 0]), None))
223
- elif st == 'asinh':
224
- c = np.arcsinh(c / stsc)
225
- elif st == 'power':
226
- cmin = kw['min'][i] if 'vmin' in kw else r
227
- c = c.clip(cmin, None)
228
- p = 1 - stretchpower
229
- c = ((c / cmin)**p - 1) / p / np.log(10)
230
- data[i] = c
289
+
231
290
  n = len(data)
232
- for m in ['vmin', 'vmax']:
233
- if m in kw:
234
- for i, (c, st, stsc, _) in enumerate(zip(*z)):
235
- if st == 'log':
236
- kw[m][i] = np.log10(kw[m][i])
237
- elif st == 'asinh':
238
- kw[m][i] = np.arcsinh(kw[m][i] / stsc)
239
- elif st == 'power':
240
- p = 1 - stretchpower
241
- kw[m][i] = ((kw[m][i]/c.min())**p - 1) / p / np.log(10)
242
- else:
243
- kw[m] = [None] * n
244
- for i, (c, st, _, r) in enumerate(zip(*z)):
245
- if m == 'vmin':
246
- kw[m][i] = np.log10(r) if st == 'log' else np.nanmin(c)
247
- else:
248
- kw[m][i] = np.nanmax(c)
291
+ if 'vmin' not in kw:
292
+ kw['vmin'] = [None] * n
293
+ if 'vmax' not in kw:
294
+ kw['vmax'] = [None] * n
295
+ stretch = np.where(np.equal(stretch, None), sigma, stretch)
296
+ minlinear = np.where(np.equal(kw['vmin'], None), sigma, kw['vmin'])
297
+
298
+ z = (stretch, stretchscale, stretchpower, minlinear)
299
+ for i, args in enumerate(zip(*z)):
300
+ st, _, _, ml = args
301
+ c = data[i]
302
+ if st in ['log', 'power']:
303
+ c = c.clip(ml, None)
304
+ c = _func_stretch(c, *args)
305
+ data[i] = c
306
+ cmin = np.nanmin(c)
307
+ cmax = np.nanmax(c)
308
+ for k in ['vmin', 'vmax']:
309
+ if kw[k][i] is None:
310
+ kw[k][i] = cmin if k == 'vmin' else cmax
311
+ else:
312
+ kw[k][i] = _func_stretch(kw[k][i], *args)
249
313
  data = [c.clip(a, b) for c, a, b in zip(data, kw['vmin'], kw['vmax'])]
250
314
  if n == 1:
251
315
  data = data[0]
@@ -787,11 +851,11 @@ class PlotAstroData(AstroFrame):
787
851
  print('No pixel size. Skip add_color.')
788
852
  return
789
853
 
790
- if stretchscale is None:
791
- stretchscale = sigma
792
- cmin_org = _kw['vmin'] if 'vmin' in _kw else sigma
854
+ minlinear = _kw['vmin'] if 'vmin' in _kw else sigma
855
+ if cblabel is None:
856
+ cblabel = bunit
857
+
793
858
  c = set_minmax(c, stretch, stretchscale, stretchpower, sigma, _kw)
794
- cmin, cmax = np.nanmin(c), np.nanmax(c)
795
859
  c = self.vskipfill(c, v)
796
860
  if type(self.channelnumber) is int:
797
861
  c = [c[self.channelnumber]]
@@ -803,8 +867,6 @@ class PlotAstroData(AstroFrame):
803
867
  for ch in self.bottomleft:
804
868
  if not show_cbar:
805
869
  break
806
- if cblabel is None:
807
- cblabel = bunit
808
870
  if self.fig is None:
809
871
  fig = plt.figure(ch // self.rowcol)
810
872
  else:
@@ -820,35 +882,20 @@ class PlotAstroData(AstroFrame):
820
882
  cb.ax.tick_params(labelsize=14)
821
883
  font = mpl.font_manager.FontProperties(size=16)
822
884
  cb.ax.yaxis.label.set_font_properties(font)
885
+ args = [stretch, stretchscale, stretchpower, minlinear]
823
886
  if cbticks is not None and ch // self.rowcol == 0:
824
- cbticks = np.array(cbticks)
825
- match stretch:
826
- case 'log':
827
- cbticks = np.log10(cbticks)
828
- case 'asinh':
829
- cbticks = np.arcsinh(cbticks / stretchscale)
830
- case 'power':
831
- p = 1 - stretchpower
832
- cbticks = (cbticks / cmin_org)**p - 1
833
- cbticks = cbticks / p / np.log(10)
834
- if stretch == 'log' and cbticks is None:
835
- cbticks, cbticklabels = logcbticks(cmin, cmax)
887
+ cbticks = _func_stretch(cbticks, *args)
888
+ if cbticks is None and stretch == 'log':
889
+ cbticks, cbticklabels = logcbticks()
836
890
  if cbticks is not None:
837
- cb.set_ticks(cbticks)
838
- if cbticklabels is not None:
839
- cb.set_ticklabels(cbticklabels)
840
- elif stretch in ['log', 'asinh', 'power']:
841
- t = cb.get_ticks()
842
- t = t[(cmin < t) * (t < cmax)]
843
- cb.set_ticks(t)
844
- if stretch == 'log':
845
- ticklin = 10**t
846
- elif stretch == 'asinh':
847
- ticklin = np.sinh(t) * stretchscale
848
- elif stretch == 'power':
849
- p = 1 - stretchpower
850
- ticklin = cmin_org * (1 + p * np.log(10) * t)**(1 / p)
851
- cb.set_ticklabels([f'{d:{cbformat[1:]}}' for d in ticklin])
891
+ cond = (_kw['vmin'] < cbticks) * (cbticks < _kw['vmax'])
892
+ cb.set_ticks(cbticks[cond])
893
+ if cbticklabels is not None:
894
+ tl = np.array(cbticklabels)[cond]
895
+ else:
896
+ t = _ifunc_stretch(cb.get_ticks(), *args)
897
+ tl = [f'{d:{cbformat[1:]}}' for d in t]
898
+ cb.set_ticklabels(tl)
852
899
  self.add_beam(beam=beam, **beam_kwargs)
853
900
 
854
901
  def add_contour(self,
@@ -940,7 +987,7 @@ class PlotAstroData(AstroFrame):
940
987
  def add_rgb(self,
941
988
  stretch: list[str, str, str] = ['linear'] * 3,
942
989
  stretchscale: list[float | None, float | None, float | None] = [None] * 3,
943
- stretchpower: float = 0,
990
+ stretchpower: list[float, float, float] = [0, 0, 0],
944
991
  **kwargs) -> None:
945
992
  """Use PIL.Image and imshow of matplotlib. kwargs must include the arguments of AstroData to specify the data to be plotted. A three-element array ([red, green, blue]) is supposed for all arguments, except for xskip, yskip and show_beam, including vmax and vmin. kwargs may include arguments for add_beam() and a dict of beam_kwargs to specify the beam patch in more detail. kwargs may include xskiip and yskip.
946
993
 
@@ -958,9 +1005,6 @@ class PlotAstroData(AstroFrame):
958
1005
  print('No pixel size. Skip add_rgb.')
959
1006
  return
960
1007
 
961
- for i in range(len(stretchscale)):
962
- if stretchscale[i] is None:
963
- stretchscale[i] = sigma[i]
964
1008
  c = set_minmax(c, stretch, stretchscale, stretchpower, sigma, _kw)
965
1009
  if not (np.shape(c[0]) == np.shape(c[1]) == np.shape(c[2])):
966
1010
  print('RGB shapes mismatch. Skip add_rgb.')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.8.5
3
+ Version: 1.8.7
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
File without changes