plotastrodata 1.8.6__tar.gz → 1.8.8__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.6/plotastrodata.egg-info → plotastrodata-1.8.8}/PKG-INFO +1 -1
  2. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/__init__.py +1 -1
  3. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/plot_utils.py +166 -107
  4. {plotastrodata-1.8.6 → plotastrodata-1.8.8/plotastrodata.egg-info}/PKG-INFO +1 -1
  5. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/LICENSE +0 -0
  6. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/MANIFEST.in +0 -0
  7. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/README.md +0 -0
  8. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/analysis_utils.py +0 -0
  9. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/const_utils.py +0 -0
  10. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/coord_utils.py +0 -0
  11. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/ext_utils.py +0 -0
  12. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/fft_utils.py +0 -0
  13. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/fits_utils.py +0 -0
  14. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/fitting_utils.py +0 -0
  15. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/los_utils.py +0 -0
  16. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/matrix_utils.py +0 -0
  17. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/noise_utils.py +0 -0
  18. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata/other_utils.py +0 -0
  19. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata.egg-info/SOURCES.txt +0 -0
  20. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata.egg-info/dependency_links.txt +0 -0
  21. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata.egg-info/not-zip-safe +0 -0
  22. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata.egg-info/requires.txt +0 -0
  23. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/plotastrodata.egg-info/top_level.txt +0 -0
  24. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/setup.cfg +0 -0
  25. {plotastrodata-1.8.6 → plotastrodata-1.8.8}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.8.6
3
+ Version: 1.8.8
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.6'
4
+ __version__ = '1.8.8'
@@ -95,6 +95,86 @@ def logcbticks(vmin: float = -3.01, vmax: float = 3.01
95
95
  return ticks, ticklabels
96
96
 
97
97
 
98
+ def pow10(x: np.ndarray, stretchpower: float) -> np.ndarray:
99
+ """A power-law function scaled by xmin. This function is used for the case of stretch='power' in PlotAstroData.add_color().
100
+
101
+ Args:
102
+ x (np.ndarray): Input in the linear scale.
103
+ stretchpower (float, optional): The output is (data**stretchpower - 1) / stretchpower / ln(10). 1 means the linear scale, while 0 means the logarithmic scale.
104
+
105
+ Returns:
106
+ np.ndarray: Output values.
107
+ """
108
+ p = 1e-6 if stretchpower == 0 else stretchpower
109
+ y = (x**p - 1) / p / np.log(10)
110
+ return y
111
+
112
+
113
+ def ipow10(x: np.ndarray, stretchpower: float) -> np.ndarray:
114
+ """The inverse function of pow10. This function is used for the case of stretch='power' in PlotAstroData.add_color().
115
+
116
+ Args:
117
+ x (np.ndarray): Input values.
118
+ stretchpower (float, optional): The input is (data**stretchpower - 1) / stretchpower / ln(10). 1 means the linear scale, while 0 means the logarithmic scale.
119
+
120
+ Returns:
121
+ np.ndarray: Output values in the linear scale.
122
+ """
123
+ p = 1e-6 if stretchpower == 0 else stretchpower
124
+ y = (1 + p * np.log(10) * x)**(1 / p)
125
+ return y
126
+
127
+
128
+ def do_stretch(x: list | np.ndarray,
129
+ stretch: str, stretchscale: float,
130
+ stretchpower: float) -> np.ndarray:
131
+ """Get the stretched values.
132
+
133
+ Args:
134
+ x (list | np.ndarray): Input array in the linear scale.
135
+ stretch (str): 'log', 'asinh', 'power', or 'linear'. Any other means 'linear'. 'log' means the mapped data are logarithmic. 'asinh' means the mapped data are arc sin hyperbolic. 'power' means the mapped data are power-law (see also stretchpower). Defaults to 'linear'.
136
+ stretchscale (float, optional): The output is asinh(data / stretchscale). Defaults to None.
137
+ stretchpower (float, optional): The output is ((data / stretchscale)**stretchpower - 1) / stretchpower / ln(10). 1 means the linear scale, while 0 means the logarithmic scale.
138
+
139
+ Returns:
140
+ np.ndarray: Output stretched array.
141
+ """
142
+ t = np.array(x)
143
+ match stretch:
144
+ case 'log':
145
+ t = np.log10(t)
146
+ case 'asinh':
147
+ t = np.arcsinh(t / stretchscale)
148
+ case 'power':
149
+ t = pow10(t / stretchscale, stretchpower)
150
+ return t
151
+
152
+
153
+ def undo_stretch(x: list | np.ndarray,
154
+ stretch: str, stretchscale: float,
155
+ stretchpower: float) -> np.ndarray:
156
+ """Get the linear values from the stretched values.
157
+
158
+ Args:
159
+ x (list | np.ndarray): Input stretched array.
160
+ stretch (str): 'log', 'asinh', 'power', or 'linear'. Any other means 'linear'. 'log' means the mapped data are logarithmic. 'asinh' means the mapped data are arc sin hyperbolic. 'power' means the mapped data are power-law (see also stretchpower). Defaults to 'linear'.
161
+ stretchscale (float, optional): The input is asinh(data / stretchscale). Defaults to None.
162
+ stretchpower (float, optional): The input is ((data / stretchscale)**stretchpower - 1) / stretchpower / ln(10). 1 means the linear scale, while 0 means the logarithmic scale.
163
+
164
+ Returns:
165
+ np.ndarray: Output array in the linear scale.
166
+ """
167
+ t = np.array(x)
168
+ match stretch:
169
+ case 'log':
170
+ t = 10**t
171
+ case 'asinh':
172
+ t = np.sinh(t) * stretchscale
173
+ case 'power':
174
+ t = ipow10(t, stretchpower) * stretchscale
175
+ return t
176
+
177
+
98
178
  @dataclass
99
179
  class PlotAxes2D():
100
180
  """Use Axes.set_* to adjust x and y axes.
@@ -199,16 +279,16 @@ class PlotAxes2D():
199
279
 
200
280
 
201
281
  def set_minmax(data: np.ndarray, stretch: str, stretchscale: float,
202
- stretchpower: float, rms: float, kw: dict
282
+ stretchpower: float, sigma: float, kw: dict
203
283
  ) -> np.ndarray:
204
284
  """Set vmin and vmax for color pcolormesh and RGB maps.
205
285
 
206
286
  Args:
207
287
  data (np.ndarray): Plotted data.
208
288
  stretch (str): 'log', 'asinh', 'power'. Any other means linear.
209
- stretchscale (float): For the arcsinh strech.
289
+ stretchscale (float): For the arcsinh strech and the power stretch.
210
290
  stretchpower (float): For the power strech.
211
- rms (float): RMS noise level.
291
+ sigma (float): Noise level.
212
292
  kw (dict): Probably like {'vmin':0, 'vmax':1}.
213
293
 
214
294
  Returns:
@@ -216,51 +296,38 @@ def set_minmax(data: np.ndarray, stretch: str, stretchscale: float,
216
296
  """
217
297
  if type(stretch) is str:
218
298
  data = [data]
219
- rms = [rms]
299
+ sigma = [sigma]
220
300
  stretch = [stretch]
221
301
  stretchscale = [stretchscale]
222
- if 'vmin' in kw:
223
- kw['vmin'] = [kw['vmin']]
224
- if 'vmax' in kw:
225
- kw['vmax'] = [kw['vmax']]
226
- z = (data, stretch, stretchscale, rms)
227
- for i, (c, st, stsc, r) in enumerate(zip(*z)):
228
- if stsc is None:
229
- stsc = r
230
- if st == 'log':
231
- if np.any(c > 0):
232
- c = np.log10(c.clip(np.nanmin(c[c > 0]), None))
233
- elif st == 'asinh':
234
- c = np.arcsinh(c / stsc)
235
- elif st == 'power':
236
- cmin = kw['min'][i] if 'vmin' in kw else r
237
- c = c.clip(cmin, None)
238
- p = 1 - stretchpower
239
- c = ((c / cmin)**p - 1) / p / np.log(10)
240
- data[i] = c
302
+ stretchpower = [stretchpower]
303
+ for k in ['vmin', 'vmax']:
304
+ if k in kw:
305
+ kw[k] = [kw[k]]
306
+
241
307
  n = len(data)
242
- for m in ['vmin', 'vmax']:
243
- if m in kw:
244
- for i, (c, st, stsc, _) in enumerate(zip(*z)):
245
- if st == 'log':
246
- kw[m][i] = np.log10(kw[m][i])
247
- elif st == 'asinh':
248
- kw[m][i] = np.arcsinh(kw[m][i] / stsc)
249
- elif st == 'power':
250
- p = 1 - stretchpower
251
- kw[m][i] = ((kw[m][i]/c.min())**p - 1) / p / np.log(10)
252
- else:
253
- kw[m] = [None] * n
254
- for i, (c, st, _, r) in enumerate(zip(*z)):
255
- if m == 'vmin':
256
- kw[m][i] = np.log10(r) if st == 'log' else np.nanmin(c)
257
- else:
258
- kw[m][i] = np.nanmax(c)
308
+ for k in ['vmin', 'vmax']:
309
+ if k not in kw:
310
+ kw[k] = [None] * n
311
+ stretch = np.where(np.equal(stretch, None), sigma, stretch)
312
+ cmin = np.where(np.equal(kw['vmin'], None), sigma, kw['vmin'])
313
+
314
+ argslist = (stretch, stretchscale, stretchpower)
315
+ for i, stretch_args in enumerate(zip(*argslist)):
316
+ c = data[i]
317
+ if stretch_args[0] in ['log', 'power']:
318
+ c = c.clip(cmin[i], None)
319
+ c = do_stretch(c, *stretch_args)
320
+ data[i] = c
321
+ for k in ['vmin', 'vmax']:
322
+ if kw[k][i] is None:
323
+ kw[k][i] = np.nanmin(c) if k == 'vmin' else np.nanmax(c)
324
+ else:
325
+ kw[k][i] = do_stretch(kw[k][i], *stretch_args)
259
326
  data = [c.clip(a, b) for c, a, b in zip(data, kw['vmin'], kw['vmax'])]
260
327
  if n == 1:
261
328
  data = data[0]
262
- kw['vmin'] = kw['vmin'][0]
263
- kw['vmax'] = kw['vmax'][0]
329
+ for k in ['vmin', 'vmax']:
330
+ kw[k] = kw[k][0]
264
331
  return data
265
332
 
266
333
 
@@ -765,10 +832,49 @@ class PlotAstroData(AstroFrame):
765
832
  axnow.plot([x[0] - length/2., x[0] + length/2.], [y[0], y[0]],
766
833
  '-', linewidth=linewidth, color=color)
767
834
 
835
+ def _set_colorbar(self, mappable, ch: int, show_cbar: bool,
836
+ cblabel: str, cbformat: str,
837
+ cbticks: list | None, cbticklabels: list | None,
838
+ cblocation: str, stretch: str,
839
+ stretchscale: float, stretchpower: float,
840
+ vmin: float, vmax: float):
841
+ if not show_cbar:
842
+ return
843
+
844
+ if self.fig is None:
845
+ fig = plt.figure(ch // self.rowcol)
846
+ else:
847
+ fig = self.fig
848
+ if len(self.ax) == 1:
849
+ ax = self.ax[ch]
850
+ cb = fig.colorbar(mappable[ch], ax=ax, label=cblabel,
851
+ format=cbformat, location=cblocation)
852
+ else:
853
+ cax = plt.axes([0.88, 0.105, 0.015, 0.77])
854
+ cb = fig.colorbar(mappable[ch], cax=cax, label=cblabel,
855
+ format=cbformat)
856
+ cb.ax.tick_params(labelsize=14)
857
+ font = mpl.font_manager.FontProperties(size=16)
858
+ cb.ax.yaxis.label.set_font_properties(font)
859
+ stretch_args = (stretch, stretchscale, stretchpower)
860
+ if cbticks is not None and ch // self.rowcol == 0:
861
+ cbticks = do_stretch(cbticks, *stretch_args)
862
+ if cbticks is None and stretch == 'log':
863
+ cbticks, cbticklabels = logcbticks()
864
+ if cbticks is not None:
865
+ cond = (vmin < cbticks) * (cbticks < vmax)
866
+ cb.set_ticks(cbticks[cond])
867
+ if cbticklabels is not None:
868
+ tl = np.array(cbticklabels)[cond]
869
+ else:
870
+ t = undo_stretch(cb.get_ticks(), *stretch_args)
871
+ tl = [f'{d:{cbformat[1:]}}' for d in t]
872
+ cb.set_ticklabels(tl)
873
+
768
874
  def add_color(self,
769
875
  stretch: str = 'linear',
770
876
  stretchscale: float | None = None,
771
- stretchpower: float = 0,
877
+ stretchpower: float = 1,
772
878
  show_cbar: bool = True,
773
879
  cblabel: str | None = None,
774
880
  cbformat: float = '%.1e',
@@ -779,9 +885,9 @@ class PlotAstroData(AstroFrame):
779
885
  """Use Axes.pcolormesh of matplotlib. kwargs must include the arguments of AstroData to specify the data to be plotted. 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.
780
886
 
781
887
  Args:
782
- stretch (str, optional): 'log' means the mapped data are logarithmic. 'asinh' means the mapped data are arc sin hyperbolic. 'power' means the mapped data are power-law (see also stretchpower). Defaults to 'linear'.
783
- stretchscale (float, optional): color scale is asinh(data / stretchscale). Defaults to None.
784
- stretchpower (float, optional): color scale is ((data / vmin)**(1 - stretchpower) - 1) / (1 - stretchpower) / ln(10). 0 means the linear scale. 1 means the logarithmic scale. Defaults to 0.
888
+ stretch (str, optional): 'log', 'asinh', 'power', or 'linear'. Any other means 'linear'. 'log' means the mapped data are logarithmic. 'asinh' means the mapped data are arc sin hyperbolic. 'power' means the mapped data are power-law (see also stretchpower). Defaults to 'linear'.
889
+ stretchscale (float, optional): Color scale is asinh(data / stretchscale). Defaults to None.
890
+ stretchpower (float, optional): Color scale is ((data / stretchscale)**stretchpower - 1) / stretchpower / ln(10). 1 means the linear scale, while 0 means the logarithmic scale. Defaults to 1.
785
891
  show_cbar (bool, optional): Show color bar. Defaults to True.
786
892
  cblabel (str, optional): Colorbar label. Defaults to None.
787
893
  cbformat (float, optional): Format for ticklabels of colorbar. Defaults to '%.1e'.
@@ -797,11 +903,11 @@ class PlotAstroData(AstroFrame):
797
903
  print('No pixel size. Skip add_color.')
798
904
  return
799
905
 
800
- if stretchscale is None:
801
- stretchscale = sigma
802
- cmin_org = _kw['vmin'] if 'vmin' in _kw else sigma
803
- c = set_minmax(c, stretch, stretchscale, stretchpower, sigma, _kw)
804
- cmin, cmax = np.nanmin(c), np.nanmax(c)
906
+ if cblabel is None:
907
+ cblabel = bunit
908
+
909
+ stretch_args = (stretch, stretchscale, stretchpower)
910
+ c = set_minmax(c, *stretch_args, sigma, _kw)
805
911
  c = self.vskipfill(c, v)
806
912
  if type(self.channelnumber) is int:
807
913
  c = [c[self.channelnumber]]
@@ -811,54 +917,9 @@ class PlotAstroData(AstroFrame):
811
917
  if ch in self.bottomleft:
812
918
  p[ch] = pnow
813
919
  for ch in self.bottomleft:
814
- if not show_cbar:
815
- break
816
- if cblabel is None:
817
- cblabel = bunit
818
- if self.fig is None:
819
- fig = plt.figure(ch // self.rowcol)
820
- else:
821
- fig = self.fig
822
- if len(self.ax) == 1:
823
- ax = self.ax[ch]
824
- cb = fig.colorbar(p[ch], ax=ax, label=cblabel,
825
- format=cbformat, location=cblocation)
826
- else:
827
- cax = plt.axes([0.88, 0.105, 0.015, 0.77])
828
- cb = fig.colorbar(p[ch], cax=cax, label=cblabel,
829
- format=cbformat)
830
- cb.ax.tick_params(labelsize=14)
831
- font = mpl.font_manager.FontProperties(size=16)
832
- cb.ax.yaxis.label.set_font_properties(font)
833
- if cbticks is not None and ch // self.rowcol == 0:
834
- cbticks = np.array(cbticks)
835
- match stretch:
836
- case 'log':
837
- cbticks = np.log10(cbticks)
838
- case 'asinh':
839
- cbticks = np.arcsinh(cbticks / stretchscale)
840
- case 'power':
841
- p = 1 - stretchpower
842
- cbticks = (cbticks / cmin_org)**p - 1
843
- cbticks = cbticks / p / np.log(10)
844
- if stretch == 'log' and cbticks is None:
845
- cbticks, cbticklabels = logcbticks(cmin, cmax)
846
- if cbticks is not None:
847
- cb.set_ticks(cbticks)
848
- if cbticklabels is not None:
849
- cb.set_ticklabels(cbticklabels)
850
- elif stretch in ['log', 'asinh', 'power']:
851
- t = cb.get_ticks()
852
- t = t[(cmin < t) * (t < cmax)]
853
- cb.set_ticks(t)
854
- if stretch == 'log':
855
- ticklin = 10**t
856
- elif stretch == 'asinh':
857
- ticklin = np.sinh(t) * stretchscale
858
- elif stretch == 'power':
859
- p = 1 - stretchpower
860
- ticklin = cmin_org * (1 + p * np.log(10) * t)**(1 / p)
861
- cb.set_ticklabels([f'{d:{cbformat[1:]}}' for d in ticklin])
920
+ self._set_colorbar(p, ch, show_cbar, cblabel, cbformat,
921
+ cbticks, cbticklabels, cblocation,
922
+ *stretch_args, _kw['vmin'], _kw['vmax'])
862
923
  self.add_beam(beam=beam, **beam_kwargs)
863
924
 
864
925
  def add_contour(self,
@@ -950,14 +1011,14 @@ class PlotAstroData(AstroFrame):
950
1011
  def add_rgb(self,
951
1012
  stretch: list[str, str, str] = ['linear'] * 3,
952
1013
  stretchscale: list[float | None, float | None, float | None] = [None] * 3,
953
- stretchpower: float = 0,
1014
+ stretchpower: list[float, float, float] = [1, 1, 1],
954
1015
  **kwargs) -> None:
955
1016
  """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.
956
1017
 
957
1018
  Args:
958
- stretch (str, optional): 'log' means the mapped data are logarithmic. 'asinh' means the mapped data are arc sin hyperbolic. 'power' means the mapped data are power-law (see also stretchpower). Defaults to 'linear'.
959
- stretchscale (float, optional): color scale is asinh(data / stretchscale). Defaults to None.
960
- stretchpower (float, optional): color scale is ((data / vmin)**(1 - stretchpower) - 1) / (1 - stretchpower) / ln(10). 0 means the linear scale. 1 means the logarithmic scale. Defaults to 0.
1019
+ stretch (str, optional): 'log', 'asinh', 'power', or 'linear'. Any other means 'linear'. 'log' means the mapped data are logarithmic. 'asinh' means the mapped data are arc sin hyperbolic. 'power' means the mapped data are power-law (see also stretchpower). Defaults to 'linear'.
1020
+ stretchscale (float, optional): Color scale is asinh(data / stretchscale). Defaults to None.
1021
+ stretchpower (float, optional): Color scale is ((data / stretchscale)**stretchpower - 1) / stretchpower / ln(10). 1 means the linear scale, while 0 means the logarithmic scale. Defaults to 1.
961
1022
  """
962
1023
  from PIL import Image
963
1024
 
@@ -968,10 +1029,8 @@ class PlotAstroData(AstroFrame):
968
1029
  print('No pixel size. Skip add_rgb.')
969
1030
  return
970
1031
 
971
- for i in range(len(stretchscale)):
972
- if stretchscale[i] is None:
973
- stretchscale[i] = sigma[i]
974
- c = set_minmax(c, stretch, stretchscale, stretchpower, sigma, _kw)
1032
+ stretch_args = (stretch, stretchscale, stretchpower)
1033
+ c = set_minmax(c, *stretch_args, sigma, _kw)
975
1034
  if not (np.shape(c[0]) == np.shape(c[1]) == np.shape(c[2])):
976
1035
  print('RGB shapes mismatch. Skip add_rgb.')
977
1036
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.8.6
3
+ Version: 1.8.8
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