plotastrodata 1.6.0__tar.gz → 1.6.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.
Files changed (23) hide show
  1. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/PKG-INFO +1 -1
  2. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/__init__.py +1 -1
  3. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/analysis_utils.py +29 -14
  4. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/other_utils.py +2 -2
  5. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/plot_utils.py +14 -7
  6. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata.egg-info/PKG-INFO +1 -1
  7. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/LICENSE +0 -0
  8. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/README.md +0 -0
  9. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/const_utils.py +0 -0
  10. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/coord_utils.py +0 -0
  11. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/ext_utils.py +0 -0
  12. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/fft_utils.py +0 -0
  13. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/fits_utils.py +0 -0
  14. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/fitting_utils.py +0 -0
  15. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/los_utils.py +0 -0
  16. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata/matrix_utils.py +0 -0
  17. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata.egg-info/SOURCES.txt +0 -0
  18. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata.egg-info/dependency_links.txt +0 -0
  19. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata.egg-info/not-zip-safe +0 -0
  20. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata.egg-info/requires.txt +0 -0
  21. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/plotastrodata.egg-info/top_level.txt +0 -0
  22. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/setup.cfg +0 -0
  23. {plotastrodata-1.6.0 → plotastrodata-1.6.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.6.0
3
+ Version: 1.6.2
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', UserWarning)
4
- __version__ = '1.6.0'
4
+ __version__ = '1.6.2'
@@ -4,7 +4,7 @@ from scipy.interpolate import RegularGridInterpolator as RGI
4
4
  from scipy.optimize import curve_fit
5
5
  from scipy.signal import convolve
6
6
 
7
- from plotastrodata.coord_utils import coord2xy, rel2abs
7
+ from plotastrodata.coord_utils import coord2xy, xy2coord, rel2abs
8
8
  from plotastrodata.matrix_utils import Mfac, Mrot, dot2d
9
9
  from plotastrodata.other_utils import (estimate_rms, trim,
10
10
  gaussian2d, isdeg,
@@ -68,7 +68,7 @@ def filled2d(data: np.ndarray, x: np.ndarray, y: np.ndarray, n: int = 1,
68
68
  return d, xnew, ynew
69
69
 
70
70
 
71
- def need_multipixel(method):
71
+ def _need_multipixels(method):
72
72
  def wrapper(self, *args, **kwargs):
73
73
  singlepixel = self.dx is None or self.dy is None
74
74
  if singlepixel:
@@ -153,9 +153,14 @@ class AstroData():
153
153
  print(f'width was changed to [{ws}].')
154
154
  newsize = size // w
155
155
  grid = [None, self.v, self.y, self.x]
156
- for n in range(4):
156
+ dgrid = [None, self.dv, self.dy, self.dx]
157
+ for n in range(1, 4):
157
158
  if w[n] == 1 or grid[n] is None:
158
159
  continue
160
+ if dgrid[n] is None:
161
+ s = ['v', 'y', 'x'][n - 1]
162
+ print(f'Skip binning in the {s}-axis because d{s} is None.')
163
+ continue
159
164
  size[n] = newsize[n]
160
165
  olddata = np.moveaxis(d, n, 0)
161
166
  newdata = np.moveaxis(np.zeros(size), n, 0)
@@ -166,9 +171,11 @@ class AstroData():
166
171
  t += grid[n][i:i_stop:i_step]
167
172
  newdata += olddata[i:i_stop:i_step]
168
173
  grid[n] = t / w[n]
174
+ dgrid[n] = dgrid[n] * w[n]
169
175
  d = np.moveaxis(newdata, 0, n) / w[n]
170
176
  self.data = np.squeeze(d)
171
177
  _, self.v, self.y, self.x = grid
178
+ _, self.dv, self.dy, self.dx = dgrid
172
179
 
173
180
  def centering(self, includexy: bool = True, includev: bool = False,
174
181
  **kwargs):
@@ -206,7 +213,7 @@ class AstroData():
206
213
  else:
207
214
  print('No change because includexy=False and includev=False.')
208
215
 
209
- @need_multipixel
216
+ @_need_multipixels
210
217
  def circularbeam(self):
211
218
  """Make the beam circular by convolving with 1D Gaussian
212
219
  """
@@ -259,7 +266,7 @@ class AstroData():
259
266
  bmin_new = 1 / np.sqrt(alpha + Det)
260
267
  self.beam = np.array([bmaj_new, bmin_new, bpa_new])
261
268
 
262
- @need_multipixel
269
+ @_need_multipixels
263
270
  def fit2d(self, model: object, bounds: np.ndarray,
264
271
  progressbar: bool = False,
265
272
  kwargs_fit: dict = {}, kwargs_plotcorner: dict = {},
@@ -307,15 +314,15 @@ class AstroData():
307
314
  return {'popt': popt, 'plow': plow, 'pmid': pmid, 'phigh': phigh,
308
315
  'model': modelopt, 'residual': residual}
309
316
 
310
- @need_multipixel
311
- def gaussfit2d(self, chan: int | None = None):
317
+ @_need_multipixels
318
+ def gaussfit2d(self, chan: int | None = None) -> dict:
312
319
  """Fit a 2D Gaussian function to self.data.
313
320
 
314
321
  Args:
315
322
  chan (int): The channel number where the 2D Gaussian is fitted. Defaults to None.
316
323
 
317
324
  Returns:
318
- dict: The best parameter set (popt), the covariance set (pcov), the best 2D Gaussian array (model), and the residual from the model (residual).
325
+ dict: The best parameter set (popt), the covariance set (pcov), the best 2D Gaussian array (model), the residual from the model (residual), and the coordinates of the best-fit center (center).
319
326
  """
320
327
  d = self.data if chan is None else self.data[chan]
321
328
  x = self.x
@@ -331,12 +338,21 @@ class AstroData():
331
338
  bounds = [[-amax, xmin, ymin, ds, ds, -90],
332
339
  [amax, xmax, ymax, smax, smax, 90]]
333
340
  x, y = np.meshgrid(x, y)
334
- popt, pcov = curve_fit(gaussian2d, (x.ravel(), y.ravel()), d.ravel(),
341
+ popt, pcov = curve_fit(gaussian2d,
342
+ (x.ravel(), y.ravel()), d.ravel(),
335
343
  p0=p0, bounds=bounds)
336
344
  model = gaussian2d((x, y), *popt)
337
345
  residual = d - model
346
+ if (center := self.center) is not None:
347
+ xy = popt[1:3] / 3600
348
+ newcenter = xy2coord(xy, coordorg=center)
349
+ if len(c := center.split()) == 3:
350
+ newcenter = f'{c[0]} {newcenter}'
351
+ else:
352
+ newcenter = None
338
353
  return {'popt': popt, 'pcov': pcov,
339
- 'model': model, 'residual': residual}
354
+ 'model': model, 'residual': residual,
355
+ 'center': newcenter}
340
356
 
341
357
  def histogram(self, **kwargs) -> tuple:
342
358
  """Output histogram of self.data using numpy.histogram. This method can take the arguments of numpy.histogram.
@@ -495,7 +511,7 @@ class AstroData():
495
511
  'sigma': self.sigma, 'center': self.center, 'pv': self.pv}
496
512
  return d
497
513
 
498
- @need_multipixel
514
+ @_need_multipixels
499
515
  def writetofits(self, fitsimage: str = 'out.fits', header: dict = {}):
500
516
  """Write out the AstroData to a FITS file.
501
517
 
@@ -629,9 +645,8 @@ class AstroFrame():
629
645
  Returns:
630
646
  np.ndarray: absolute coordinates.
631
647
  """
632
- if np.shape(poslist) == () \
633
- or (np.shape(poslist) == (2,)
634
- and type(poslist[0]) is not str):
648
+ onexy = np.shape(poslist) == (2,) and type(poslist[0]) is not str
649
+ if np.shape(poslist) == () or onexy:
635
650
  poslist = [poslist]
636
651
  x, y = [None] * len(poslist), [None] * len(poslist)
637
652
  for i, p in enumerate(poslist):
@@ -12,10 +12,10 @@ def listing(*args) -> list:
12
12
  Returns:
13
13
  list: With a single non-list input, the output is a list like ['a'], rather than [['a']].
14
14
  """
15
- nums = [float, int, np.float64, np.int64, np.float32, np.int32]
15
+ strnum = [str, float, int, np.float64, np.int64, np.float32, np.int32]
16
16
  b = [None] * len(args)
17
17
  for i, a in enumerate(args):
18
- b[i] = [a] if type(a) in (nums + [str]) else a
18
+ b[i] = [a] if type(a) in strnum else a
19
19
  if len(args) == 1:
20
20
  b = b[0]
21
21
  return b
@@ -513,8 +513,9 @@ class PlotAstroData(AstroFrame):
513
513
  if patch not in ['rectangle', 'ellipse']:
514
514
  print('Only patch=\'rectangle\' or \'ellipse\' supported. ')
515
515
  return
516
- for x, y, width, height, angle in zip(*self.pos2xy(poslist),
517
- *listing(minlist, majlist, palist)):
516
+
517
+ z = listing(*self.pos2xy(poslist), minlist, majlist, palist)
518
+ for x, y, width, height, angle in zip(*z):
518
519
  for ch, axnow in enumerate(self.ax):
519
520
  if type(self.channelnumber) is int:
520
521
  ch = self.channelnumber
@@ -549,12 +550,15 @@ class PlotAstroData(AstroFrame):
549
550
  """
550
551
  if not show_beam:
551
552
  return
552
- include_chan = self.bottomleft if self.channelnumber is None else self.allchan
553
+
554
+ animation = self.channelnumber is not None
555
+ include_chan = self.allchan if animation else self.bottomleft
553
556
  patch = 'rectangle' if self.pv else 'ellipse'
554
557
  blist = [beam] if np.ndim(beam) == 1 else beam
555
558
  n = len(blist)
556
559
  bclist = beamcolor if type(beamcolor) is list else [beamcolor] * n
557
- bplist = beampos if beampos == [None] * 3 or np.ndim(beampos) == 2 else [beampos] * n
560
+ islist = beampos == [None] * 3 or np.ndim(beampos) == 2
561
+ bplist = beampos if islist else [beampos] * n
558
562
  for (bmaj, bmin, bpa), bc, bp in zip(blist, bclist, bplist):
559
563
  if None in [bmaj, bmin, bpa]:
560
564
  print('No beam to plot.')
@@ -613,7 +617,8 @@ class PlotAstroData(AstroFrame):
613
617
  ch = self.channelnumber
614
618
  if ch not in include_chan:
615
619
  continue
616
- for x, y, s in zip(*self.pos2xy(poslist), listing(slist)):
620
+ z = listing(*self.pos2xy(poslist), slist)
621
+ for x, y, s in zip(*z):
617
622
  axnow.text(x=x, y=y, s=s, **_kw)
618
623
 
619
624
  def add_line(self, poslist: list[str | list[float, float]] = [],
@@ -639,7 +644,8 @@ class PlotAstroData(AstroFrame):
639
644
  if ch not in include_chan:
640
645
  continue
641
646
  alist = np.radians(anglelist)
642
- for x, y, a, r in zip(*self.pos2xy(poslist), *listing(alist, rlist)):
647
+ z = listing(*self.pos2xy(poslist), alist, rlist)
648
+ for x, y, a, r in zip(*z):
643
649
  axnow.plot([x, x + r * np.sin(a)],
644
650
  [y, y + r * np.cos(a)], **_kw)
645
651
 
@@ -666,7 +672,8 @@ class PlotAstroData(AstroFrame):
666
672
  if ch not in include_chan:
667
673
  continue
668
674
  alist = np.radians(anglelist)
669
- for x, y, a, r in zip(*self.pos2xy(poslist), *listing(alist, rlist)):
675
+ z = listing(*self.pos2xy(poslist), alist, rlist)
676
+ for x, y, a, r in zip(*z):
670
677
  axnow.quiver(x, y, r * np.sin(a), r * np.cos(a),
671
678
  angles='xy', scale_units='xy', scale=1,
672
679
  **_kw)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.6.0
3
+ Version: 1.6.2
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