plotastrodata 1.9.9__tar.gz → 1.9.10__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.9.9/plotastrodata.egg-info → plotastrodata-1.9.10}/PKG-INFO +1 -1
  2. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/__init__.py +1 -1
  3. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/analysis_utils.py +22 -22
  4. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/coord_utils.py +4 -4
  5. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/fits_utils.py +19 -19
  6. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/fitting_utils.py +2 -2
  7. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/noise_utils.py +4 -4
  8. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/other_utils.py +4 -4
  9. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/plot_utils.py +58 -74
  10. {plotastrodata-1.9.9 → plotastrodata-1.9.10/plotastrodata.egg-info}/PKG-INFO +1 -1
  11. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/LICENSE +0 -0
  12. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/MANIFEST.in +0 -0
  13. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/README.md +0 -0
  14. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/const_utils.py +0 -0
  15. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/ext_utils.py +0 -0
  16. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/fft_utils.py +0 -0
  17. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/los_utils.py +0 -0
  18. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata/matrix_utils.py +0 -0
  19. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata.egg-info/SOURCES.txt +0 -0
  20. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata.egg-info/dependency_links.txt +0 -0
  21. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata.egg-info/not-zip-safe +0 -0
  22. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata.egg-info/requires.txt +0 -0
  23. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/plotastrodata.egg-info/top_level.txt +0 -0
  24. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/setup.cfg +0 -0
  25. {plotastrodata-1.9.9 → plotastrodata-1.9.10}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.9.9
3
+ Version: 1.9.10
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.9.9'
4
+ __version__ = '1.9.10'
@@ -117,7 +117,7 @@ class AstroData():
117
117
  def __post_init__(self):
118
118
  n = 0
119
119
  if self.fitsimage is not None:
120
- if type(self.fitsimage) is not list:
120
+ if not isinstance(self.fitsimage, list):
121
121
  n = 1
122
122
  elif any(a is not None for a in self.fitsimage):
123
123
  n = len(self.fitsimage)
@@ -126,7 +126,7 @@ class AstroData():
126
126
  if n > 0:
127
127
  self.data = None
128
128
  if self.data is not None:
129
- if type(self.data) is not list:
129
+ if not isinstance(self.data, list):
130
130
  n = 1
131
131
  elif any(a is not None for a in self.data):
132
132
  n = len(self.data)
@@ -590,9 +590,9 @@ def _get_gridsep(axis: np.ndarray | None):
590
590
  return axis[1] - axis[0] if axis is not None and len(axis) > 1 else None
591
591
 
592
592
 
593
- ASTRODATA_ARGS = ["fitsimage", "data", "Tb", "sigma", "center", "restfreq",
594
- "cfactor", "bunit", "fitsimage_org", "sigma_org",
595
- "beam_org", "fitsheader", "pv", "pvpa"]
593
+ ASTRODATA_ARGS = ['fitsimage', 'data', 'Tb', 'sigma', 'center', 'restfreq',
594
+ 'cfactor', 'bunit', 'fitsimage_org', 'sigma_org',
595
+ 'beam_org', 'fitsheader', 'pv', 'pvpa']
596
596
 
597
597
 
598
598
  @dataclass
@@ -675,12 +675,12 @@ class AstroFrame():
675
675
  Returns:
676
676
  np.ndarray: absolute coordinates.
677
677
  """
678
- onexy = np.shape(poslist) == (2,) and type(poslist[0]) is not str
678
+ onexy = np.shape(poslist) == (2,) and not isinstance(poslist[0], str)
679
679
  if np.shape(poslist) == () or onexy:
680
680
  poslist = [poslist]
681
681
  x, y = [None] * len(poslist), [None] * len(poslist)
682
682
  for i, p in enumerate(poslist):
683
- if type(p) is str:
683
+ if isinstance(p, str):
684
684
  x[i], y[i] = coord2xy(p, self.center) * 3600.
685
685
  else:
686
686
  x[i], y[i] = rel2abs(*p, self.Xlim, self.Ylim)
@@ -688,12 +688,12 @@ class AstroFrame():
688
688
 
689
689
  def _get_restfreq(self, header: dict):
690
690
  """Extract rest frequency from FITS header."""
691
- if "RESTFRQ" in header:
692
- return header["RESTFRQ"]
693
- if "RESTFREQ" in header:
694
- return header["RESTFREQ"]
695
- if "NAXIS3" in header and header["NAXIS3"] == 1 and not self.pv:
696
- return header["CRVAL3"]
691
+ if 'RESTFRQ' in header:
692
+ return header['RESTFRQ']
693
+ if 'RESTFREQ' in header:
694
+ return header['RESTFREQ']
695
+ if 'NAXIS3' in header and header['NAXIS3'] == 1 and not self.pv:
696
+ return header['CRVAL3']
697
697
  return None
698
698
 
699
699
  def _read_fitsimage(self, d: AstroData, i: int, grid: list) -> list:
@@ -715,7 +715,7 @@ class AstroFrame():
715
715
  if fd.wcsrot:
716
716
  d.center[i] = fd.get_center()
717
717
  d.beam[i] = fd.get_beam(dist=self.dist)
718
- d.bunit[i] = fd.get_header("BUNIT")
718
+ d.bunit[i] = fd.get_header('BUNIT')
719
719
  return grid
720
720
 
721
721
  def _shift_center(self, d: AstroData, i: int, grid: list) -> list:
@@ -758,7 +758,7 @@ class AstroFrame():
758
758
  if self.pv:
759
759
  d.v = d.y
760
760
  for axis in ['x', 'y', 'v']:
761
- setattr(d, f"d{axis}", _get_gridsep(getattr(d, axis)))
761
+ setattr(d, f'd{axis}', _get_gridsep(getattr(d, axis)))
762
762
 
763
763
  def _convert_to_Tb(self, d: AstroData, i: int):
764
764
  """Convert Jy/beam data to brightness temperature if requested."""
@@ -766,12 +766,12 @@ class AstroFrame():
766
766
  return
767
767
 
768
768
  dx = d.dy if self.swapxy else d.dx
769
- header = {"CDELT1": dx / 3600,
770
- "CUNIT1": "DEG",
771
- "RESTFREQ": d.restfreq[i]}
769
+ header = {'CDELT1': dx / 3600,
770
+ 'CUNIT1': 'deg',
771
+ 'RESTFREQ': d.restfreq[i]}
772
772
  if None not in d.beam[i]:
773
- header["BMAJ"] = d.beam[i][0] / 3600 / self.dist
774
- header["BMIN"] = d.beam[i][1] / 3600 / self.dist
773
+ header['BMAJ'] = d.beam[i][0] / 3600 / self.dist
774
+ header['BMIN'] = d.beam[i][1] / 3600 / self.dist
775
775
  factor = Jy2K(header=header)
776
776
  d.data[i] = d.data[i] * factor
777
777
  if d.sigma[i] is not None:
@@ -785,7 +785,7 @@ class AstroFrame():
785
785
  bmaj, bmin, bpa = d.beam_org[i] = d.beam[i]
786
786
  if d.pvpa[i] is None:
787
787
  d.pvpa[i] = bpa
788
- print("pvpa is not specified. pvpa=bpa is assumed.")
788
+ print('pvpa is not specified. pvpa=bpa is assumed.')
789
789
  angle = np.radians(bpa - d.pvpa[i])
790
790
  beam_incut = 1 / np.hypot(np.cos(angle) / bmaj, np.sin(angle) / bmin)
791
791
  d.beam[i] = np.array([np.abs(d.dv), beam_incut, 0])
@@ -827,5 +827,5 @@ class AstroFrame():
827
827
  d.beam = _as_list(d.beam, d.n, isbeam=True)
828
828
  for i in range(d.n):
829
829
  self._read_one(d, i)
830
- for name in ASTRODATA_ARGS + ["beam"]:
830
+ for name in ASTRODATA_ARGS + ['beam']:
831
831
  setattr(d, name, _scalar_if_single(getattr(d, name), d.n))
@@ -18,7 +18,7 @@ def _updateframe(frame: str) -> str:
18
18
  a = FK5(equinox='J2000')
19
19
  elif 'B1950' in frame or 'FK4' in frame:
20
20
  a = FK4(equinox='B1950')
21
- elif type(frame) is str:
21
+ elif isinstance(frame, str):
22
22
  print(f'Unknown frame ({frame}) was found. Use ICRS instead.')
23
23
  a = 'icrs'
24
24
  else:
@@ -26,7 +26,7 @@ def _updateframe(frame: str) -> str:
26
26
  return a
27
27
 
28
28
 
29
- def _getframe(coord: str) -> tuple:
29
+ def _getframe(coord: str | list) -> tuple:
30
30
  """Internal function to pick up the frame name from the coordinates. When coord is a list, frame and framename are picked up from the first element.
31
31
 
32
32
  Args:
@@ -43,7 +43,7 @@ def _getframe(coord: str) -> tuple:
43
43
  framename = c[0] if hasframe else None
44
44
  return hmsdms, frame, framename
45
45
 
46
- if type(coord) is str:
46
+ if isinstance(coord, str):
47
47
  return getframe_single(coord)
48
48
  else:
49
49
  outlist = [getframe_single(c) for c in coord]
@@ -108,7 +108,7 @@ def xy2coord(xy: list, coordorg: str = '00h00m00s 00d00m00s',
108
108
  coords = coords.transform_to(frame=frame)
109
109
  coords = coords.to_string('hmsdms')
110
110
  if framename is not None:
111
- if type(coords) is str:
111
+ if isinstance(coords, str):
112
112
  coords = f'{framename} {coords}'
113
113
  else:
114
114
  coords = np.array([f'{framename} {s}' for s in coords])
@@ -241,23 +241,23 @@ class FitsData:
241
241
  h = self.header
242
242
  cxy = (0, 0)
243
243
  if center is not None and not self.wcsrot:
244
- coordorg = xy2coord([h["CRVAL1"], h["CRVAL2"]])
245
- if (radesys := h.get("RADESYS")) is not None:
246
- coordorg = f"{radesys} {coordorg}"
244
+ coordorg = xy2coord([h['CRVAL1'], h['CRVAL2']])
245
+ if (radesys := h.get('RADESYS')) is not None:
246
+ coordorg = f'{radesys} {coordorg}'
247
247
  cxy = coord2xy(center, coordorg)
248
- slabel = ["x", "y"]
248
+ slabel = ['x', 'y']
249
249
 
250
250
  def wrapper(i: int):
251
251
  def gen_s(s_in: np.ndarray | None) -> None:
252
- if h.get(f"NAXIS{i+1}") is None or s_in is None:
252
+ if h.get(f'NAXIS{i+1}') is None or s_in is None:
253
253
  s, ds = None, None
254
254
  else:
255
255
  s = (s_in - cxy[i]) * dist
256
- if isdeg(h[f"CUNIT{i+1}"]):
256
+ if isdeg(h[f'CUNIT{i+1}']):
257
257
  s *= 3600.
258
258
  ds = None if len(s) == 0 else s[1] - s[0]
259
- setattr(self, f"{slabel[i]}", s)
260
- setattr(self, f"d{slabel[i]}", ds)
259
+ setattr(self, f'{slabel[i]}', s)
260
+ setattr(self, f'd{slabel[i]}', ds)
261
261
  return gen_s
262
262
 
263
263
  return wrapper(0), wrapper(1)
@@ -266,29 +266,29 @@ class FitsData:
266
266
  h = self.header
267
267
 
268
268
  def gen_v(v_in: np.ndarray) -> None:
269
- vaxis = "2" if pv else "3"
270
- if h.get(f"NAXIS{vaxis}") is None or v_in is None:
269
+ vaxis = '2' if pv else '3'
270
+ if h.get(f'NAXIS{vaxis}') is None or v_in is None:
271
271
  self.v, self.dv = None, None
272
272
  return
273
273
 
274
274
  if restfreq is None:
275
275
  freq = np.mean(v_in)
276
- print("restfreq is assumed to be the center.")
276
+ print('restfreq is assumed to be the center.')
277
277
  else:
278
278
  freq = restfreq
279
- v = v_in + h[f"CRVAL{vaxis}"]
279
+ v = v_in + h[f'CRVAL{vaxis}']
280
280
  key = f'CUNIT{vaxis}'
281
281
  cunitv = h[key].strip()
282
282
  match cunitv:
283
- case "Hz" | "HZ":
283
+ case 'Hz' | 'HZ':
284
284
  if freq == 0:
285
- print("v is read as is, because restfreq=0.")
285
+ print('v is read as is, because restfreq=0.')
286
286
  else:
287
287
  v = (1 - v / freq) * cu.c_kms - vsys
288
- case "m/s" | "M/S":
288
+ case 'm/s' | 'M/S':
289
289
  print(f'{key}={cunitv} found.')
290
290
  v = v * 1e-3 - vsys
291
- case 'km/s' | "KM/S":
291
+ case 'km/s' | 'KM/S':
292
292
  print(f'{key}={cunitv} found.')
293
293
  v = v - vsys
294
294
  case _:
@@ -301,11 +301,11 @@ class FitsData:
301
301
 
302
302
  def _get_array(self, i: int) -> np.ndarray:
303
303
  h = self.header
304
- n = h.get(f"NAXIS{i:d}")
304
+ n = h.get(f'NAXIS{i:d}')
305
305
  if n is None:
306
306
  return None
307
307
 
308
- s = (np.arange(n) - h[f"CRPIX{i:d}"] + 1) * h[f"CDELT{i:d}"]
308
+ s = (np.arange(n) - h[f'CRPIX{i:d}'] + 1) * h[f'CDELT{i:d}']
309
309
  return s
310
310
 
311
311
  def gen_grid(self, center: str | None = None, dist: float = 1.,
@@ -343,7 +343,7 @@ class FitsData:
343
343
  Returns:
344
344
  tuple: (x, y, v).
345
345
  """
346
- if not np.all([hasattr(self, s) for s in ["x", "y", "v"]]):
346
+ if not np.all([hasattr(self, s) for s in ['x', 'y', 'v']]):
347
347
  self.gen_grid(**kwargs)
348
348
  return self.x, self.y, self.v
349
349
 
@@ -290,9 +290,9 @@ class EmceeCorner():
290
290
  log (list, optional): Whether to search in the logarithmic space. The percentile is counted in the linear space regardless of this option. Defaults to False.
291
291
  pcut (float, optional): Posterior is reset to be zero if it is below this cut off.
292
292
  """
293
- if type(ngrid) is int:
293
+ if isinstance(ngrid, int):
294
294
  ngrid = [ngrid] * self.dim
295
- if type(log) is bool:
295
+ if isinstance(log, bool):
296
296
  log = [log] * self.dim
297
297
  pargrid = []
298
298
  inzip = [self.bounds[:, 0], self.bounds[:, 1], ngrid, log]
@@ -1,4 +1,5 @@
1
1
  import matplotlib.pyplot as plt
2
+ import numbers
2
3
  import numpy as np
3
4
  import warnings
4
5
  from scipy.special import erf
@@ -12,7 +13,7 @@ def normalize(range: tuple = (-3.5, 3.5), bins: int = 100):
12
13
  def decorator(f):
13
14
  h = np.linspace(*range, bins + 1)
14
15
  h = (h[1:] + h[:-1]) / 2
15
- dh = (range[1] - range[0]) / 100
16
+ dh = h[1] - h[0]
16
17
 
17
18
  def wrapper(x, *args):
18
19
  area = np.sum(f(h, *args)) * dh
@@ -73,7 +74,7 @@ def select_noise(data: np.ndarray, sigma: str) -> np.ndarray:
73
74
  Returns:
74
75
  np.ndarray: 1D array that includes only the selected pixels.
75
76
  """
76
- n = data * 1
77
+ n = np.array(data) * 1
77
78
  if 'edge' in sigma:
78
79
  if np.ndim(n) <= 2:
79
80
  print('\'edge\' is ignored because ndim <= 2.')
@@ -194,8 +195,7 @@ def estimate_rms(data: np.ndarray,
194
195
  Returns:
195
196
  float: The estimated standard deviation of noise.
196
197
  """
197
- nums = [float, int, np.float64, np.int64, np.float32, np.int32]
198
- if sigma is None or type(sigma) in nums:
198
+ if sigma is None or isinstance(sigma, numbers.Number):
199
199
  return sigma
200
200
 
201
201
  if np.ndim(np.squeeze(data)) == 0:
@@ -1,4 +1,5 @@
1
1
  import matplotlib.pyplot as plt
2
+ import numbers
2
3
  import numpy as np
3
4
  import warnings
4
5
  from scipy.interpolate import RegularGridInterpolator as RGI
@@ -10,10 +11,9 @@ def listing(*args) -> list:
10
11
  Returns:
11
12
  list: With a single non-list input, the output is a list like ['a'], rather than [['a']].
12
13
  """
13
- strnum = [str, float, int, np.float64, np.int64, np.float32, np.int32]
14
14
  b = [None] * len(args)
15
15
  for i, a in enumerate(args):
16
- b[i] = [a] if type(a) in strnum else a
16
+ b[i] = [a] if isinstance(a, (str, numbers.Number)) else a
17
17
  if len(args) == 1:
18
18
  b = b[0]
19
19
  return b
@@ -28,7 +28,7 @@ def isdeg(s: str) -> bool:
28
28
  Returns:
29
29
  bool: Whether the given string means degree.
30
30
  """
31
- if type(s) is str:
31
+ if isinstance(s, str):
32
32
  return s.strip() in ['deg', 'DEG', 'degree', 'DEGREE']
33
33
  else:
34
34
  return False
@@ -86,7 +86,7 @@ def trim(data: np.ndarray | None = None, x: np.ndarray | None = None,
86
86
  d = np.squeeze(data)
87
87
 
88
88
  if d.ndim == 0:
89
- print("data has only one pixel.")
89
+ print('data has only one pixel.')
90
90
  return data, [xout, yout, vout]
91
91
 
92
92
  if d.ndim == 2:
@@ -177,9 +177,13 @@ def _get_ch2nij(nrows: int = 1, ncols: int = 1) -> object:
177
177
  return ch2nij
178
178
 
179
179
 
180
- def _get_vskipfill(nv: float, v_org: np.ndarray, vskip: int) -> object:
180
+ def _get_vskipfill(nv: float, v_org: np.ndarray, vskip: int,
181
+ channelnumber: int) -> object:
181
182
  def vskipfill(c: np.ndarray, v_in: np.ndarray) -> np.ndarray:
182
- return reform_data(c=c, v_in=v_in, nv=nv, v_org=v_org, vskip=vskip)
183
+ c = reform_data(c=c, v_in=v_in, nv=nv, v_org=v_org, vskip=vskip)
184
+ if isinstance(channelnumber, int):
185
+ c = [c[channelnumber]]
186
+ return c
183
187
  return vskipfill
184
188
 
185
189
 
@@ -203,7 +207,7 @@ class Stretcher():
203
207
  sigma: float = 0
204
208
 
205
209
  def __post_init__(self):
206
- self.n = 1 if type(self.stretch) is str else len(self.stretch)
210
+ self.n = 1 if isinstance(self.stretch, str) else len(self.stretch)
207
211
  stretch = self.stretch
208
212
  stsc = self.stretchscale
209
213
  vmin = self.vmin
@@ -372,8 +376,8 @@ class PlotAxes2D():
372
376
  if self.loglog is not None:
373
377
  self.xscale = self.yscale = 'log'
374
378
  self.samexy = True
375
- for axis in ["x", "y"]:
376
- attr = f"{axis}lim"
379
+ for axis in ['x', 'y']:
380
+ attr = f'{axis}lim'
377
381
  lim = getattr(self, attr)
378
382
  if lim is not None:
379
383
  lim[0] = lim[1] / self.loglog
@@ -383,14 +387,14 @@ class PlotAxes2D():
383
387
 
384
388
  def _init_ticks(self, axis):
385
389
  ax = self.ax
386
- ticks_attr = f"{axis}ticks"
387
- ticklabels_attr = f"{axis}ticklabels"
388
- scale = getattr(self, f"{axis}scale")
389
- lim = getattr(self, f"{axis}lim")
390
+ ticks_attr = f'{axis}ticks'
391
+ ticklabels_attr = f'{axis}ticklabels'
392
+ scale = getattr(self, f'{axis}scale')
393
+ lim = getattr(self, f'{axis}lim')
390
394
  ticks = getattr(self, ticks_attr)
391
395
  if ticks is None:
392
- ticks = getattr(ax, f"get_{axis}ticks")()
393
- if scale == "log":
396
+ ticks = getattr(ax, f'get_{axis}ticks')()
397
+ if scale == 'log':
394
398
  ticks, ticklabels = logticks(ticks, lim)
395
399
  setattr(self, ticklabels_attr, ticklabels)
396
400
  setattr(self, ticks_attr, ticks)
@@ -403,21 +407,21 @@ class PlotAxes2D():
403
407
 
404
408
  def _set_ticks(self, axis):
405
409
  ax = self.ax
406
- attr = f"{axis}ticks"
410
+ attr = f'{axis}ticks'
407
411
  ticks = getattr(self, attr)
408
- getattr(ax, f"set_{attr}")(ticks)
409
- ticksminor = getattr(self, f"{attr}minor")
412
+ getattr(ax, f'set_{attr}')(ticks)
413
+ ticksminor = getattr(self, f'{attr}minor')
410
414
  if ticksminor is not None:
411
415
  if isinstance(ticksminor, int):
412
416
  ticksminor = self._make_ticks(ticks, ticksminor)
413
- getattr(ax, f"set_{attr}")(ticksminor, minor=True)
417
+ getattr(ax, f'set_{attr}')(ticksminor, minor=True)
414
418
 
415
419
  def _apply_if_not_none(self, axis, attr):
416
420
  ax = self.ax
417
- method = getattr(ax, f"set_{axis}{attr}")
418
- value = getattr(self, f"{axis}{attr}")
421
+ method = getattr(ax, f'set_{axis}{attr}')
422
+ value = getattr(self, f'{axis}{attr}')
419
423
  if value is not None:
420
- if attr == "lim":
424
+ if attr == 'lim':
421
425
  method(*value)
422
426
  else:
423
427
  method(value)
@@ -429,10 +433,10 @@ class PlotAxes2D():
429
433
  ax.set_xticks(ax.get_yticks())
430
434
  ax.set_yticks(ax.get_xticks())
431
435
  ax.set_aspect(1)
432
- for axis in ["x", "y"]:
436
+ for axis in ['x', 'y']:
433
437
  self._init_ticks(axis)
434
438
  self._set_ticks(axis)
435
- for attr in ["ticklabels", "label", "lim"]:
439
+ for attr in ['ticklabels', 'label', 'lim']:
436
440
  self._apply_if_not_none(axis, attr)
437
441
  if self.grid is not None:
438
442
  ax.grid(**({} if self.grid is True else self.grid))
@@ -514,9 +518,10 @@ class PlotAstroData(AstroFrame):
514
518
  super().__init__(**kwargs)
515
519
  internalfig = fig is None
516
520
  internalax = ax is None
521
+ animation = isinstance(channelnumber, int)
517
522
  v = _get_v(p=self, v=v, restfreq=restfreq, vskip=vskip)
518
523
  nv = len(v) # number of channels with a label
519
- if self.pv or len(v) == 1 or channelnumber is not None:
524
+ if self.pv or len(v) == 1 or animation:
520
525
  nrows = ncols = npages = nchan = 1
521
526
  else:
522
527
  npages = int(np.ceil(nv / nrows / ncols))
@@ -532,7 +537,7 @@ class PlotAstroData(AstroFrame):
532
537
  ymin=self.ymin, ymax=self.ymax,
533
538
  figsize=figsize,
534
539
  ncols=ncols, nrows=nrows, nchan=nchan)
535
- need_vlabel = nchan > 1 or type(channelnumber) is int
540
+ need_vlabel = nchan > 1 or animation
536
541
  for ch in range(nchan):
537
542
  n, i, j = ch2nij(ch)
538
543
  if internalfig and n not in plt.get_fignums():
@@ -557,8 +562,9 @@ class PlotAstroData(AstroFrame):
557
562
  self.allchan = np.arange(nv)
558
563
  self.bottomleft = nij2ch(np.arange(npages), nrows - 1, 0)
559
564
  self.channelnumber = channelnumber
565
+ self.animation = animation
560
566
  self.v = v
561
- self.vskipfill = _get_vskipfill(nv=nv, v_org=v, vskip=vskip)
567
+ self.vskipfill = _get_vskipfill(nv, v, vskip, channelnumber)
562
568
 
563
569
  def _map_init(self, kw: dict) -> tuple:
564
570
  """
@@ -587,6 +593,12 @@ class PlotAstroData(AstroFrame):
587
593
  return (d.data, d.x, d.y, d.v, d.sigma, d.bunit,
588
594
  self._kw, singlepix)
589
595
 
596
+ def _validchan(self, include_chan: list) -> list:
597
+ chans = self.allchan if include_chan is None else include_chan
598
+ if self.animation:
599
+ chans = [0] if self.channelnumber in include_chan else [1]
600
+ return chans
601
+
590
602
  def add_region(self, patch: str = 'ellipse',
591
603
  poslist: list[str | list[float, float]] = [],
592
604
  majlist: list[float] = [], minlist: list[float] = [],
@@ -606,8 +618,6 @@ class PlotAstroData(AstroFrame):
606
618
  _kw = {'facecolor': 'none', 'edgecolor': 'gray',
607
619
  'linewidth': 1.5, 'zorder': 10}
608
620
  _kw.update(kwargs)
609
- if include_chan is None:
610
- include_chan = self.allchan
611
621
  if patch not in ['rectangle', 'ellipse']:
612
622
  print('Only patch=\'rectangle\' or \'ellipse\' supported. ')
613
623
  return
@@ -615,9 +625,7 @@ class PlotAstroData(AstroFrame):
615
625
  z = listing(*self.pos2xy(poslist), minlist, majlist, palist)
616
626
  for x, y, width, height, angle in zip(*z):
617
627
  for ch, axnow in enumerate(self.ax):
618
- if type(self.channelnumber) is int:
619
- ch = self.channelnumber
620
- if ch not in include_chan:
628
+ if ch not in self._validchan(include_chan):
621
629
  continue
622
630
  if self.fig is None:
623
631
  plt.figure(ch // self.rowcol)
@@ -643,12 +651,11 @@ class PlotAstroData(AstroFrame):
643
651
  if not show_beam:
644
652
  return
645
653
 
646
- animation = self.channelnumber is not None
647
- include_chan = self.allchan if animation else self.bottomleft
654
+ include_chan = self.allchan if self.animation else self.bottomleft
648
655
  patch = 'rectangle' if self.pv else 'ellipse'
649
656
  blist = [beam] if np.ndim(beam) == 1 else beam
650
657
  n = len(blist)
651
- bclist = beamcolor if type(beamcolor) is list else [beamcolor] * n
658
+ bclist = beamcolor if isinstance(beamcolor, list) else [beamcolor] * n
652
659
  islist = beampos == [None] * 3 or np.ndim(beampos) == 2
653
660
  bplist = beampos if islist else [beampos] * n
654
661
  for (bmaj, bmin, bpa), bc, bp in zip(blist, bclist, bplist):
@@ -679,12 +686,8 @@ class PlotAstroData(AstroFrame):
679
686
  _kw = {'marker': '+', 'ms': 10, 'mfc': 'gray',
680
687
  'mec': 'gray', 'mew': 2, 'alpha': 1, 'zorder': 10}
681
688
  _kw.update(kwargs)
682
- if include_chan is None:
683
- include_chan = self.allchan
684
689
  for ch, axnow in enumerate(self.ax):
685
- if type(self.channelnumber) is int:
686
- ch = self.channelnumber
687
- if ch not in include_chan:
690
+ if ch not in self._validchan(include_chan):
688
691
  continue
689
692
  for x, y in zip(*self.pos2xy(poslist)):
690
693
  axnow.plot(x, y, **_kw)
@@ -707,12 +710,8 @@ class PlotAstroData(AstroFrame):
707
710
  if long in kwargs:
708
711
  kwargs[short] = kwargs.pop(long)
709
712
  _kw.update(kwargs)
710
- if include_chan is None:
711
- include_chan = self.allchan
712
713
  for ch, axnow in enumerate(self.ax):
713
- if type(self.channelnumber) is int:
714
- ch = self.channelnumber
715
- if ch not in include_chan:
714
+ if ch not in self._validchan(include_chan):
716
715
  continue
717
716
  z = listing(*self.pos2xy(poslist), slist)
718
717
  for x, y, s in zip(*z):
@@ -733,12 +732,8 @@ class PlotAstroData(AstroFrame):
733
732
  _kw = {'color': 'gray', 'linewidth': 1.5,
734
733
  'linestyle': '-', 'zorder': 10}
735
734
  _kw.update(kwargs)
736
- if include_chan is None:
737
- include_chan = self.allchan
738
735
  for ch, axnow in enumerate(self.ax):
739
- if type(self.channelnumber) is int:
740
- ch = self.channelnumber
741
- if ch not in include_chan:
736
+ if ch not in self._validchan(include_chan):
742
737
  continue
743
738
  alist = np.radians(anglelist)
744
739
  z = listing(*self.pos2xy(poslist), alist, rlist)
@@ -761,12 +756,8 @@ class PlotAstroData(AstroFrame):
761
756
  _kw = {'color': 'gray', 'width': 0.012,
762
757
  'headwidth': 5, 'headlength': 5, 'zorder': 10}
763
758
  _kw.update(kwargs)
764
- if include_chan is None:
765
- include_chan = self.allchan
766
759
  for ch, axnow in enumerate(self.ax):
767
- if type(self.channelnumber) is int:
768
- ch = self.channelnumber
769
- if ch not in include_chan:
760
+ if ch not in self._validchan(include_chan):
770
761
  continue
771
762
  alist = np.radians(anglelist)
772
763
  z = listing(*self.pos2xy(poslist), alist, rlist)
@@ -878,8 +869,6 @@ class PlotAstroData(AstroFrame):
878
869
  _kw['vmin'] = cmin
879
870
  _kw['vmax'] = cmax
880
871
  c = self.vskipfill(c, v)
881
- if type(self.channelnumber) is int:
882
- c = [c[self.channelnumber]]
883
872
  p = [None] * len(self.ax)
884
873
  for ch, (axnow, cnow) in enumerate(zip(self.ax, c)):
885
874
  pnow = axnow.pcolormesh(x, y, cnow, **_kw)
@@ -905,8 +894,6 @@ class PlotAstroData(AstroFrame):
905
894
  return
906
895
 
907
896
  c = self.vskipfill(c, v)
908
- if type(self.channelnumber) is int:
909
- c = [c[self.channelnumber]]
910
897
  for axnow, cnow in zip(self.ax, c):
911
898
  axnow.contour(x, y, cnow, np.sort(levels) * sigma, **_kw)
912
899
 
@@ -963,9 +950,6 @@ class PlotAstroData(AstroFrame):
963
950
  V = ampfactor * amp * np.cos(np.radians(ang + rotation))
964
951
  U = self.vskipfill(U, v)
965
952
  V = self.vskipfill(V, v)
966
- if type(self.channelnumber) is int:
967
- U = [U[self.channelnumber]]
968
- V = [V[self.channelnumber]]
969
953
  _kw['scale'] = 1. / np.abs(x[1] - x[0])
970
954
  for axnow, unow, vnow in zip(self.ax, U, V):
971
955
  axnow.quiver(x, y, unow, vnow, **_kw)
@@ -1027,13 +1011,13 @@ class PlotAstroData(AstroFrame):
1027
1011
  if title is not None:
1028
1012
  if len(self.ax) > 1:
1029
1013
  t = {'y': 0.9}
1030
- t_in = {'t': title} if type(title) is str else title
1014
+ t_in = {'t': title} if isinstance(title, str) else title
1031
1015
  t.update(t_in)
1032
1016
  for i in range(self.npages):
1033
1017
  fig = plt.figure(i)
1034
1018
  fig.suptitle(**t)
1035
1019
  else:
1036
- t = {'label': title} if type(title) is str else title
1020
+ t = {'label': title} if isinstance(title, str) else title
1037
1021
  axnow.set_title(**t)
1038
1022
 
1039
1023
  def set_axis(self, title: dict | str | None = None, **kwargs) -> None:
@@ -1173,7 +1157,7 @@ class PlotAstroData(AstroFrame):
1173
1157
  for axnow in self.ax:
1174
1158
  axnow.set_xlim(*self.Xlim)
1175
1159
  axnow.set_ylim(*self.Ylim)
1176
- if type(filename) is str:
1160
+ if isinstance(filename, str):
1177
1161
  ext = filename.split('.')[-1]
1178
1162
  for i in range(self.npages):
1179
1163
  ver = '' if self.npages == 1 else f'_{i:d}'
@@ -1202,12 +1186,12 @@ class PlotAstroData(AstroFrame):
1202
1186
 
1203
1187
  def _get_ylabel_profile(_kw: dict, Tb: bool, flux: bool, bunit: str
1204
1188
  ) -> str:
1205
- if "ylabel" in _kw:
1206
- return _kw["ylabel"]
1189
+ if 'ylabel' in _kw:
1190
+ return _kw['ylabel']
1207
1191
  if Tb:
1208
- return r"$T_b$ (K)"
1192
+ return r'$T_b$ (K)'
1209
1193
  if flux:
1210
- return "Flux (Jy)"
1194
+ return 'Flux (Jy)'
1211
1195
  return bunit
1212
1196
 
1213
1197
 
@@ -1217,7 +1201,7 @@ def _prep_plotprofile(width: int, coords: list | str,
1217
1201
  _kw: dict) -> tuple:
1218
1202
  if isinstance(coords, str):
1219
1203
  coords = [coords]
1220
- Tb = _kw.get("Tb", False)
1204
+ Tb = _kw.get('Tb', False)
1221
1205
  f = kwargs2instance(AstroFrame, _kw)
1222
1206
  d = kwargs2instance(AstroData, _kw)
1223
1207
  f.read(d)
@@ -1228,7 +1212,7 @@ def _prep_plotprofile(width: int, coords: list | str,
1228
1212
  ylabel = _get_ylabel_profile(_kw, Tb, flux, d.bunit)
1229
1213
  if isinstance(ylabel, str):
1230
1214
  ylabel = [ylabel] * len(prof)
1231
- _kw.setdefault("xlim", [v.min(), v.max()])
1215
+ _kw.setdefault('xlim', [v.min(), v.max()])
1232
1216
  pa2 = kwargs2instance(PlotAxes2D, _kw)
1233
1217
  return v, prof, gfitres, pa2, ylabel
1234
1218
 
@@ -1240,7 +1224,7 @@ def _set_figax_plotprofile(fig, ax, nrows: int, ncols: int,
1240
1224
  if fig is None:
1241
1225
  fig = plt.figure(figsize=(6 * ncols, 3 * nrows))
1242
1226
  if nprof > 1 and ax is not None:
1243
- print("External ax is supported only when len(coords)=1.")
1227
+ print('External ax is supported only when len(coords)=1.')
1244
1228
  ax = None
1245
1229
  ax = np.empty(nprof, dtype=object) if ax is None else [ax]
1246
1230
  for i in range(nprof):
@@ -1287,8 +1271,8 @@ def plotprofile(coords: list[str] | str = [],
1287
1271
  Returns:
1288
1272
  tuple: (fig, ax), where ax is a list, if getfigax=True. Otherwise, no return.
1289
1273
  """
1290
- _kw = {"drawstyle": "steps-mid", "color": "k",
1291
- "xlabel": r"Velocity (km s$^{-1}$)", "samexy": False}
1274
+ _kw = {'drawstyle': 'steps-mid', 'color': 'k',
1275
+ 'xlabel': r'Velocity (km s$^{-1}$)', 'samexy': False}
1292
1276
  _kw.update(kwargs)
1293
1277
  _kwgauss = {'drawstyle': 'default', 'color': 'g'}
1294
1278
  _kwgauss.update(gauss_kwargs)
@@ -1296,20 +1280,20 @@ def plotprofile(coords: list[str] | str = [],
1296
1280
  = _prep_plotprofile(width, coords, xlist, ylist, ellipse,
1297
1281
  ninterp, flux, gaussfit, _kw)
1298
1282
  nprof = len(prof)
1299
- set_rcparams(20, "w")
1283
+ set_rcparams(20, 'w')
1300
1284
  fig, ax = _set_figax_plotprofile(fig, ax, nrows, ncols, nprof)
1301
1285
  for i in range(nprof):
1302
1286
  if gaussfit:
1303
- ax[i].plot(v, gaussian1d(v, *gfitres["best"][i]), **_kwgauss)
1287
+ ax[i].plot(v, gaussian1d(v, *gfitres['best'][i]), **_kwgauss)
1304
1288
  ax[i].plot(v, prof[i], **_kw)
1305
- ax[i].hlines([0], v.min(), v.max(), linestyle="dashed", color="k")
1289
+ ax[i].hlines([0], v.min(), v.max(), linestyle='dashed', color='k')
1306
1290
  ax[i].set_ylabel(ylabel[i])
1307
1291
  pa2.set_xyaxes(ax[i])
1308
1292
  if text is not None:
1309
1293
  ax[i].text(**text[i])
1310
1294
  if title is not None:
1311
1295
  if isinstance(title[i], str):
1312
- title[i] = {"label": title[i]}
1296
+ title[i] = {'label': title[i]}
1313
1297
  ax[i].set_title(**title[i])
1314
1298
  if i <= nprof - ncols - 1:
1315
1299
  plt.setp(ax[i].get_xticklabels(), visible=False)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.9.9
3
+ Version: 1.9.10
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