plotastrodata 1.9.8__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.8/plotastrodata.egg-info → plotastrodata-1.9.10}/PKG-INFO +1 -1
  2. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/__init__.py +1 -1
  3. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/analysis_utils.py +22 -22
  4. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/coord_utils.py +4 -4
  5. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/fits_utils.py +19 -19
  6. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/fitting_utils.py +2 -2
  7. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/noise_utils.py +4 -4
  8. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/other_utils.py +4 -4
  9. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/plot_utils.py +168 -165
  10. {plotastrodata-1.9.8 → plotastrodata-1.9.10/plotastrodata.egg-info}/PKG-INFO +1 -1
  11. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/LICENSE +0 -0
  12. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/MANIFEST.in +0 -0
  13. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/README.md +0 -0
  14. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/const_utils.py +0 -0
  15. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/ext_utils.py +0 -0
  16. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/fft_utils.py +0 -0
  17. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/los_utils.py +0 -0
  18. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata/matrix_utils.py +0 -0
  19. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata.egg-info/SOURCES.txt +0 -0
  20. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata.egg-info/dependency_links.txt +0 -0
  21. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata.egg-info/not-zip-safe +0 -0
  22. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata.egg-info/requires.txt +0 -0
  23. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/plotastrodata.egg-info/top_level.txt +0 -0
  24. {plotastrodata-1.9.8 → plotastrodata-1.9.10}/setup.cfg +0 -0
  25. {plotastrodata-1.9.8 → 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.8
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.8'
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:
@@ -8,6 +8,7 @@ from typing import TypeVar
8
8
  from plotastrodata.analysis_utils import AstroData, AstroFrame
9
9
  from plotastrodata.coord_utils import (coord2xy, xy2coord,
10
10
  get_hmdm, get_min, get_sec)
11
+ from plotastrodata.fitting_utils import gaussian1d
11
12
  from plotastrodata.noise_utils import estimate_rms
12
13
  from plotastrodata.other_utils import (close_figure, listing,
13
14
  reform_grid, reform_data)
@@ -176,9 +177,13 @@ def _get_ch2nij(nrows: int = 1, ncols: int = 1) -> object:
176
177
  return ch2nij
177
178
 
178
179
 
179
- 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:
180
182
  def vskipfill(c: np.ndarray, v_in: np.ndarray) -> np.ndarray:
181
- 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
182
187
  return vskipfill
183
188
 
184
189
 
@@ -202,7 +207,7 @@ class Stretcher():
202
207
  sigma: float = 0
203
208
 
204
209
  def __post_init__(self):
205
- 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)
206
211
  stretch = self.stretch
207
212
  stsc = self.stretchscale
208
213
  vmin = self.vmin
@@ -371,8 +376,8 @@ class PlotAxes2D():
371
376
  if self.loglog is not None:
372
377
  self.xscale = self.yscale = 'log'
373
378
  self.samexy = True
374
- for axis in ["x", "y"]:
375
- attr = f"{axis}lim"
379
+ for axis in ['x', 'y']:
380
+ attr = f'{axis}lim'
376
381
  lim = getattr(self, attr)
377
382
  if lim is not None:
378
383
  lim[0] = lim[1] / self.loglog
@@ -382,14 +387,14 @@ class PlotAxes2D():
382
387
 
383
388
  def _init_ticks(self, axis):
384
389
  ax = self.ax
385
- ticks_attr = f"{axis}ticks"
386
- ticklabels_attr = f"{axis}ticklabels"
387
- scale = getattr(self, f"{axis}scale")
388
- 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')
389
394
  ticks = getattr(self, ticks_attr)
390
395
  if ticks is None:
391
- ticks = getattr(ax, f"get_{axis}ticks")()
392
- if scale == "log":
396
+ ticks = getattr(ax, f'get_{axis}ticks')()
397
+ if scale == 'log':
393
398
  ticks, ticklabels = logticks(ticks, lim)
394
399
  setattr(self, ticklabels_attr, ticklabels)
395
400
  setattr(self, ticks_attr, ticks)
@@ -402,21 +407,21 @@ class PlotAxes2D():
402
407
 
403
408
  def _set_ticks(self, axis):
404
409
  ax = self.ax
405
- attr = f"{axis}ticks"
410
+ attr = f'{axis}ticks'
406
411
  ticks = getattr(self, attr)
407
- getattr(ax, f"set_{attr}")(ticks)
408
- ticksminor = getattr(self, f"{attr}minor")
412
+ getattr(ax, f'set_{attr}')(ticks)
413
+ ticksminor = getattr(self, f'{attr}minor')
409
414
  if ticksminor is not None:
410
415
  if isinstance(ticksminor, int):
411
416
  ticksminor = self._make_ticks(ticks, ticksminor)
412
- getattr(ax, f"set_{attr}")(ticksminor, minor=True)
417
+ getattr(ax, f'set_{attr}')(ticksminor, minor=True)
413
418
 
414
419
  def _apply_if_not_none(self, axis, attr):
415
420
  ax = self.ax
416
- method = getattr(ax, f"set_{axis}{attr}")
417
- value = getattr(self, f"{axis}{attr}")
421
+ method = getattr(ax, f'set_{axis}{attr}')
422
+ value = getattr(self, f'{axis}{attr}')
418
423
  if value is not None:
419
- if attr == "lim":
424
+ if attr == 'lim':
420
425
  method(*value)
421
426
  else:
422
427
  method(value)
@@ -428,10 +433,10 @@ class PlotAxes2D():
428
433
  ax.set_xticks(ax.get_yticks())
429
434
  ax.set_yticks(ax.get_xticks())
430
435
  ax.set_aspect(1)
431
- for axis in ["x", "y"]:
436
+ for axis in ['x', 'y']:
432
437
  self._init_ticks(axis)
433
438
  self._set_ticks(axis)
434
- for attr in ["ticklabels", "label", "lim"]:
439
+ for attr in ['ticklabels', 'label', 'lim']:
435
440
  self._apply_if_not_none(axis, attr)
436
441
  if self.grid is not None:
437
442
  ax.grid(**({} if self.grid is True else self.grid))
@@ -513,9 +518,10 @@ class PlotAstroData(AstroFrame):
513
518
  super().__init__(**kwargs)
514
519
  internalfig = fig is None
515
520
  internalax = ax is None
521
+ animation = isinstance(channelnumber, int)
516
522
  v = _get_v(p=self, v=v, restfreq=restfreq, vskip=vskip)
517
523
  nv = len(v) # number of channels with a label
518
- if self.pv or len(v) == 1 or channelnumber is not None:
524
+ if self.pv or len(v) == 1 or animation:
519
525
  nrows = ncols = npages = nchan = 1
520
526
  else:
521
527
  npages = int(np.ceil(nv / nrows / ncols))
@@ -531,7 +537,7 @@ class PlotAstroData(AstroFrame):
531
537
  ymin=self.ymin, ymax=self.ymax,
532
538
  figsize=figsize,
533
539
  ncols=ncols, nrows=nrows, nchan=nchan)
534
- need_vlabel = nchan > 1 or type(channelnumber) is int
540
+ need_vlabel = nchan > 1 or animation
535
541
  for ch in range(nchan):
536
542
  n, i, j = ch2nij(ch)
537
543
  if internalfig and n not in plt.get_fignums():
@@ -556,8 +562,9 @@ class PlotAstroData(AstroFrame):
556
562
  self.allchan = np.arange(nv)
557
563
  self.bottomleft = nij2ch(np.arange(npages), nrows - 1, 0)
558
564
  self.channelnumber = channelnumber
565
+ self.animation = animation
559
566
  self.v = v
560
- self.vskipfill = _get_vskipfill(nv=nv, v_org=v, vskip=vskip)
567
+ self.vskipfill = _get_vskipfill(nv, v, vskip, channelnumber)
561
568
 
562
569
  def _map_init(self, kw: dict) -> tuple:
563
570
  """
@@ -586,6 +593,12 @@ class PlotAstroData(AstroFrame):
586
593
  return (d.data, d.x, d.y, d.v, d.sigma, d.bunit,
587
594
  self._kw, singlepix)
588
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
+
589
602
  def add_region(self, patch: str = 'ellipse',
590
603
  poslist: list[str | list[float, float]] = [],
591
604
  majlist: list[float] = [], minlist: list[float] = [],
@@ -605,8 +618,6 @@ class PlotAstroData(AstroFrame):
605
618
  _kw = {'facecolor': 'none', 'edgecolor': 'gray',
606
619
  'linewidth': 1.5, 'zorder': 10}
607
620
  _kw.update(kwargs)
608
- if include_chan is None:
609
- include_chan = self.allchan
610
621
  if patch not in ['rectangle', 'ellipse']:
611
622
  print('Only patch=\'rectangle\' or \'ellipse\' supported. ')
612
623
  return
@@ -614,9 +625,7 @@ class PlotAstroData(AstroFrame):
614
625
  z = listing(*self.pos2xy(poslist), minlist, majlist, palist)
615
626
  for x, y, width, height, angle in zip(*z):
616
627
  for ch, axnow in enumerate(self.ax):
617
- if type(self.channelnumber) is int:
618
- ch = self.channelnumber
619
- if ch not in include_chan:
628
+ if ch not in self._validchan(include_chan):
620
629
  continue
621
630
  if self.fig is None:
622
631
  plt.figure(ch // self.rowcol)
@@ -642,12 +651,11 @@ class PlotAstroData(AstroFrame):
642
651
  if not show_beam:
643
652
  return
644
653
 
645
- animation = self.channelnumber is not None
646
- include_chan = self.allchan if animation else self.bottomleft
654
+ include_chan = self.allchan if self.animation else self.bottomleft
647
655
  patch = 'rectangle' if self.pv else 'ellipse'
648
656
  blist = [beam] if np.ndim(beam) == 1 else beam
649
657
  n = len(blist)
650
- bclist = beamcolor if type(beamcolor) is list else [beamcolor] * n
658
+ bclist = beamcolor if isinstance(beamcolor, list) else [beamcolor] * n
651
659
  islist = beampos == [None] * 3 or np.ndim(beampos) == 2
652
660
  bplist = beampos if islist else [beampos] * n
653
661
  for (bmaj, bmin, bpa), bc, bp in zip(blist, bclist, bplist):
@@ -678,12 +686,8 @@ class PlotAstroData(AstroFrame):
678
686
  _kw = {'marker': '+', 'ms': 10, 'mfc': 'gray',
679
687
  'mec': 'gray', 'mew': 2, 'alpha': 1, 'zorder': 10}
680
688
  _kw.update(kwargs)
681
- if include_chan is None:
682
- include_chan = self.allchan
683
689
  for ch, axnow in enumerate(self.ax):
684
- if type(self.channelnumber) is int:
685
- ch = self.channelnumber
686
- if ch not in include_chan:
690
+ if ch not in self._validchan(include_chan):
687
691
  continue
688
692
  for x, y in zip(*self.pos2xy(poslist)):
689
693
  axnow.plot(x, y, **_kw)
@@ -706,12 +710,8 @@ class PlotAstroData(AstroFrame):
706
710
  if long in kwargs:
707
711
  kwargs[short] = kwargs.pop(long)
708
712
  _kw.update(kwargs)
709
- if include_chan is None:
710
- include_chan = self.allchan
711
713
  for ch, axnow in enumerate(self.ax):
712
- if type(self.channelnumber) is int:
713
- ch = self.channelnumber
714
- if ch not in include_chan:
714
+ if ch not in self._validchan(include_chan):
715
715
  continue
716
716
  z = listing(*self.pos2xy(poslist), slist)
717
717
  for x, y, s in zip(*z):
@@ -732,12 +732,8 @@ class PlotAstroData(AstroFrame):
732
732
  _kw = {'color': 'gray', 'linewidth': 1.5,
733
733
  'linestyle': '-', 'zorder': 10}
734
734
  _kw.update(kwargs)
735
- if include_chan is None:
736
- include_chan = self.allchan
737
735
  for ch, axnow in enumerate(self.ax):
738
- if type(self.channelnumber) is int:
739
- ch = self.channelnumber
740
- if ch not in include_chan:
736
+ if ch not in self._validchan(include_chan):
741
737
  continue
742
738
  alist = np.radians(anglelist)
743
739
  z = listing(*self.pos2xy(poslist), alist, rlist)
@@ -760,12 +756,8 @@ class PlotAstroData(AstroFrame):
760
756
  _kw = {'color': 'gray', 'width': 0.012,
761
757
  'headwidth': 5, 'headlength': 5, 'zorder': 10}
762
758
  _kw.update(kwargs)
763
- if include_chan is None:
764
- include_chan = self.allchan
765
759
  for ch, axnow in enumerate(self.ax):
766
- if type(self.channelnumber) is int:
767
- ch = self.channelnumber
768
- if ch not in include_chan:
760
+ if ch not in self._validchan(include_chan):
769
761
  continue
770
762
  alist = np.radians(anglelist)
771
763
  z = listing(*self.pos2xy(poslist), alist, rlist)
@@ -877,8 +869,6 @@ class PlotAstroData(AstroFrame):
877
869
  _kw['vmin'] = cmin
878
870
  _kw['vmax'] = cmax
879
871
  c = self.vskipfill(c, v)
880
- if type(self.channelnumber) is int:
881
- c = [c[self.channelnumber]]
882
872
  p = [None] * len(self.ax)
883
873
  for ch, (axnow, cnow) in enumerate(zip(self.ax, c)):
884
874
  pnow = axnow.pcolormesh(x, y, cnow, **_kw)
@@ -904,8 +894,6 @@ class PlotAstroData(AstroFrame):
904
894
  return
905
895
 
906
896
  c = self.vskipfill(c, v)
907
- if type(self.channelnumber) is int:
908
- c = [c[self.channelnumber]]
909
897
  for axnow, cnow in zip(self.ax, c):
910
898
  axnow.contour(x, y, cnow, np.sort(levels) * sigma, **_kw)
911
899
 
@@ -962,9 +950,6 @@ class PlotAstroData(AstroFrame):
962
950
  V = ampfactor * amp * np.cos(np.radians(ang + rotation))
963
951
  U = self.vskipfill(U, v)
964
952
  V = self.vskipfill(V, v)
965
- if type(self.channelnumber) is int:
966
- U = [U[self.channelnumber]]
967
- V = [V[self.channelnumber]]
968
953
  _kw['scale'] = 1. / np.abs(x[1] - x[0])
969
954
  for axnow, unow, vnow in zip(self.ax, U, V):
970
955
  axnow.quiver(x, y, unow, vnow, **_kw)
@@ -1026,13 +1011,13 @@ class PlotAstroData(AstroFrame):
1026
1011
  if title is not None:
1027
1012
  if len(self.ax) > 1:
1028
1013
  t = {'y': 0.9}
1029
- t_in = {'t': title} if type(title) is str else title
1014
+ t_in = {'t': title} if isinstance(title, str) else title
1030
1015
  t.update(t_in)
1031
1016
  for i in range(self.npages):
1032
1017
  fig = plt.figure(i)
1033
1018
  fig.suptitle(**t)
1034
1019
  else:
1035
- t = {'label': title} if type(title) is str else title
1020
+ t = {'label': title} if isinstance(title, str) else title
1036
1021
  axnow.set_title(**t)
1037
1022
 
1038
1023
  def set_axis(self, title: dict | str | None = None, **kwargs) -> None:
@@ -1172,7 +1157,7 @@ class PlotAstroData(AstroFrame):
1172
1157
  for axnow in self.ax:
1173
1158
  axnow.set_xlim(*self.Xlim)
1174
1159
  axnow.set_ylim(*self.Ylim)
1175
- if type(filename) is str:
1160
+ if isinstance(filename, str):
1176
1161
  ext = filename.split('.')[-1]
1177
1162
  for i in range(self.npages):
1178
1163
  ver = '' if self.npages == 1 else f'_{i:d}'
@@ -1199,6 +1184,55 @@ class PlotAstroData(AstroFrame):
1199
1184
  return fig, self.ax[0]
1200
1185
 
1201
1186
 
1187
+ def _get_ylabel_profile(_kw: dict, Tb: bool, flux: bool, bunit: str
1188
+ ) -> str:
1189
+ if 'ylabel' in _kw:
1190
+ return _kw['ylabel']
1191
+ if Tb:
1192
+ return r'$T_b$ (K)'
1193
+ if flux:
1194
+ return 'Flux (Jy)'
1195
+ return bunit
1196
+
1197
+
1198
+ def _prep_plotprofile(width: int, coords: list | str,
1199
+ xlist: list, ylist: list, ellipse: list,
1200
+ ninterp: int, flux: bool, gaussfit: bool,
1201
+ _kw: dict) -> tuple:
1202
+ if isinstance(coords, str):
1203
+ coords = [coords]
1204
+ Tb = _kw.get('Tb', False)
1205
+ f = kwargs2instance(AstroFrame, _kw)
1206
+ d = kwargs2instance(AstroData, _kw)
1207
+ f.read(d)
1208
+ d.binning([width, 1, 1])
1209
+ v, prof, gfitres = d.profile(coords=coords, xlist=xlist, ylist=ylist,
1210
+ ellipse=ellipse, ninterp=ninterp,
1211
+ flux=flux, gaussfit=gaussfit)
1212
+ ylabel = _get_ylabel_profile(_kw, Tb, flux, d.bunit)
1213
+ if isinstance(ylabel, str):
1214
+ ylabel = [ylabel] * len(prof)
1215
+ _kw.setdefault('xlim', [v.min(), v.max()])
1216
+ pa2 = kwargs2instance(PlotAxes2D, _kw)
1217
+ return v, prof, gfitres, pa2, ylabel
1218
+
1219
+
1220
+ def _set_figax_plotprofile(fig, ax, nrows: int, ncols: int,
1221
+ nprof: int) -> tuple:
1222
+ if ncols == 1:
1223
+ nrows = nprof
1224
+ if fig is None:
1225
+ fig = plt.figure(figsize=(6 * ncols, 3 * nrows))
1226
+ if nprof > 1 and ax is not None:
1227
+ print('External ax is supported only when len(coords)=1.')
1228
+ ax = None
1229
+ ax = np.empty(nprof, dtype=object) if ax is None else [ax]
1230
+ for i in range(nprof):
1231
+ sharex = None if i < nrows - 1 else ax[i - 1]
1232
+ ax[i] = fig.add_subplot(nrows, ncols, i + 1, sharex=sharex)
1233
+ return fig, ax
1234
+
1235
+
1202
1236
  def plotprofile(coords: list[str] | str = [],
1203
1237
  xlist: list[float] = [], ylist: list[float] = [],
1204
1238
  ellipse: list[float, float, float] | None = None,
@@ -1208,11 +1242,9 @@ def plotprofile(coords: list[str] | str = [],
1208
1242
  title: list[str] | None = None,
1209
1243
  text: list[str] | None = None,
1210
1244
  nrows: int = 0, ncols: int = 1,
1211
- fig: object | None = None,
1212
- ax: object | None = None,
1245
+ fig: object | None = None, ax: object | None = None,
1213
1246
  getfigax: bool = False,
1214
- savefig: dict | str | None = None,
1215
- show: bool = False,
1247
+ savefig: dict | str | None = None, show: bool = False,
1216
1248
  **kwargs) -> tuple[object, object]:
1217
1249
  """Use Axes.plot of matplotlib to plot line profiles at given coordinates. kwargs must include the arguments of AstroData to specify the data to be plotted. kwargs must include the arguments of AstroFrame to specify the ranges and so on for plotting. kwargs can include the arguments of PlotAxes2D to adjust x and y axes.
1218
1250
 
@@ -1239,54 +1271,20 @@ def plotprofile(coords: list[str] | str = [],
1239
1271
  Returns:
1240
1272
  tuple: (fig, ax), where ax is a list, if getfigax=True. Otherwise, no return.
1241
1273
  """
1242
- _kw = {'drawstyle': 'steps-mid', 'color': 'k'}
1274
+ _kw = {'drawstyle': 'steps-mid', 'color': 'k',
1275
+ 'xlabel': r'Velocity (km s$^{-1}$)', 'samexy': False}
1243
1276
  _kw.update(kwargs)
1244
1277
  _kwgauss = {'drawstyle': 'default', 'color': 'g'}
1245
1278
  _kwgauss.update(gauss_kwargs)
1246
- if type(coords) is str:
1247
- coords = [coords]
1248
- f = kwargs2instance(AstroFrame, _kw)
1249
- d = kwargs2instance(AstroData, _kw)
1250
- f.read(d)
1251
- d.binning([width, 1, 1])
1252
- v, prof, gfitres = d.profile(coords=coords, xlist=xlist, ylist=ylist,
1253
- ellipse=ellipse, ninterp=ninterp,
1254
- flux=flux, gaussfit=gaussfit)
1279
+ v, prof, gfitres, pa2, ylabel \
1280
+ = _prep_plotprofile(width, coords, xlist, ylist, ellipse,
1281
+ ninterp, flux, gaussfit, _kw)
1255
1282
  nprof = len(prof)
1256
- if 'ylabel' in _kw:
1257
- ylabel = _kw['ylabel']
1258
- elif d.Tb:
1259
- ylabel = r'$T_b$ (K)'
1260
- elif flux:
1261
- ylabel = 'Flux (Jy)'
1262
- else:
1263
- ylabel = d.bunit
1264
- if type(ylabel) is str:
1265
- ylabel = [ylabel] * nprof
1266
-
1267
- def gauss(x, p, c, w):
1268
- return p * np.exp(-4. * np.log(2.) * ((x - c) / w)**2)
1269
-
1270
1283
  set_rcparams(20, 'w')
1271
- if ncols == 1:
1272
- nrows = nprof
1273
- if fig is None:
1274
- fig = plt.figure(figsize=(6 * ncols, 3 * nrows))
1275
- if nprof > 1 and ax is not None:
1276
- print('External ax is supported only when len(coords)=1.')
1277
- ax = None
1278
- ax = np.empty(nprof, dtype='object') if ax is None else [ax]
1279
- if 'xlabel' not in _kw:
1280
- _kw['xlabel'] = 'Velocity (km s$^{-1}$)'
1281
- if 'xlim' not in _kw:
1282
- _kw['xlim'] = [v.min(), v.max()]
1283
- _kw['samexy'] = False
1284
- pa2 = kwargs2instance(PlotAxes2D, _kw)
1284
+ fig, ax = _set_figax_plotprofile(fig, ax, nrows, ncols, nprof)
1285
1285
  for i in range(nprof):
1286
- sharex = None if i < nrows - 1 else ax[i - 1]
1287
- ax[i] = fig.add_subplot(nrows, ncols, i + 1, sharex=sharex)
1288
1286
  if gaussfit:
1289
- ax[i].plot(v, gauss(v, *gfitres['best'][i]), **_kwgauss)
1287
+ ax[i].plot(v, gaussian1d(v, *gfitres['best'][i]), **_kwgauss)
1290
1288
  ax[i].plot(v, prof[i], **_kw)
1291
1289
  ax[i].hlines([0], v.min(), v.max(), linestyle='dashed', color='k')
1292
1290
  ax[i].set_ylabel(ylabel[i])
@@ -1294,7 +1292,7 @@ def plotprofile(coords: list[str] | str = [],
1294
1292
  if text is not None:
1295
1293
  ax[i].text(**text[i])
1296
1294
  if title is not None:
1297
- if type(title[i]) is str:
1295
+ if isinstance(title[i], str):
1298
1296
  title[i] = {'label': title[i]}
1299
1297
  ax[i].set_title(**title[i])
1300
1298
  if i <= nprof - ncols - 1:
@@ -1369,8 +1367,69 @@ def plotslice(length: float, dx: float | None = None, pa: float = 0,
1369
1367
  close_figure(fig, savefig, show)
1370
1368
 
1371
1369
 
1370
+ def _plot_on_wall(d: AstroData, x: np.ndarray, y: np.ndarray, v: np.ndarray,
1371
+ measure: object, datalist: list,
1372
+ sign: int, axis: int, **kwargs):
1373
+ dx, dy, dv = x[1] - x[0], y[1] - y[0], v[1] - v[0]
1374
+ s, ds = [x, y, v], [dx, dy, dv]
1375
+ if kwargs == {}:
1376
+ return
1377
+
1378
+ match axis:
1379
+ case 2:
1380
+ shape = np.shape(d.data[:, :, 0])
1381
+ case 1:
1382
+ shape = np.shape(d.data[:, 0, :])
1383
+ case 0:
1384
+ shape = np.shape(d.data[0, :, :])
1385
+ if np.shape(kwargs['data']) != shape:
1386
+ print('The shape of the 2D data is inconsistent'
1387
+ + ' with the shape of the 3D data.')
1388
+ return
1389
+
1390
+ _kw = {'levels': [3, 6, 12, 24, 48, 96, 192, 384],
1391
+ 'sigma': 'hist', 'cmap': 'Jet', 'alpha': 0.3}
1392
+ _kw.update(kwargs)
1393
+ volume = _kw['data']
1394
+ levels = _kw['levels']
1395
+ cmap = _kw['cmap']
1396
+ alpha = _kw['alpha']
1397
+ sigma = estimate_rms(data=volume, sigma=_kw['sigma'])
1398
+ volume[np.isnan(volume)] = 0
1399
+ a = int(sign == -1)
1400
+ b = int(sign == 1)
1401
+ volume = np.moveaxis([volume * a, volume * b], 0, axis)
1402
+ if d.dx < 0:
1403
+ volume = volume[:, :, ::-1]
1404
+ if d.dy < 0:
1405
+ volume = volume[:, ::-1, :]
1406
+ if d.dv < 0:
1407
+ volume = volume[::-1, :, :]
1408
+ for lev in levels:
1409
+ if lev * sigma > np.max(volume):
1410
+ continue
1411
+ vertices, simplices, _, _ = measure.marching_cubes(volume, lev * sigma)
1412
+ Xg, Yg, Zg = [t[0] + i * dt for t, i, dt
1413
+ in zip(s, vertices.T[::-1], ds)]
1414
+ match axis:
1415
+ case 2:
1416
+ Xg = Xg * 0 + (x[-1] if sign == 1 else x[0])
1417
+ case 1:
1418
+ Yg = Yg * 0 + (y[-1] if sign == 1 else y[0])
1419
+ case 0:
1420
+ Zg = Zg * 0 + (v[-1] if sign == 1 else v[0])
1421
+ i, j, k = simplices.T
1422
+ mesh2d = dict(type='mesh3d', x=Xg, y=Yg, z=Zg,
1423
+ i=i, j=j, k=k,
1424
+ intensity=Zg * 0 + lev,
1425
+ colorscale=cmap, reversescale=False,
1426
+ cmin=np.min(levels), cmax=np.max(levels),
1427
+ opacity=alpha, name='', showscale=False)
1428
+ datalist.append(mesh2d)
1429
+
1430
+
1372
1431
  def plot3d(levels: list[float] = [3, 6, 12],
1373
- cmap: str = 'Jet', alpha: float = 0.08,
1432
+ cmap: str = 'jet', alpha: float = 0.08,
1374
1433
  xlabel: str = 'R.A. (arcsec)',
1375
1434
  ylabel: str = 'Dec. (arcsec)',
1376
1435
  vlabel: str = 'Velocity (km/s)',
@@ -1461,67 +1520,11 @@ def plot3d(levels: list[float] = [3, 6, 12],
1461
1520
  name='', line=dict(color='rgb(0,0,0)', width=1))
1462
1521
  data.append(lines)
1463
1522
 
1464
- def plot_on_wall(sign: int, axis: int, **kwargs):
1465
- if kwargs == {}:
1466
- return
1467
-
1468
- match axis:
1469
- case 2:
1470
- shape = np.shape(d.data[:, :, 0])
1471
- case 1:
1472
- shape = np.shape(d.data[:, 0, :])
1473
- case 0:
1474
- shape = np.shape(d.data[0, :, :])
1475
- if np.shape(kwargs['data']) != shape:
1476
- print('The shape of the 2D data is inconsistent'
1477
- + ' with the shape of the 3D data.')
1478
- return
1479
-
1480
- _kw = {'levels': [3, 6, 12, 24, 48, 96, 192, 384],
1481
- 'sigma': 'hist', 'cmap': 'Jet', 'alpha': 0.3}
1482
- _kw.update(kwargs)
1483
- volume = _kw['data']
1484
- levels = _kw['levels']
1485
- cmap = _kw['cmap']
1486
- alpha = _kw['alpha']
1487
- sigma = estimate_rms(data=volume, sigma=_kw['sigma'])
1488
- volume[np.isnan(volume)] = 0
1489
- a = int(sign == -1)
1490
- b = int(sign == 1)
1491
- volume = np.moveaxis([volume * a, volume * b], 0, axis)
1492
- if d.dx < 0:
1493
- volume = volume[:, :, ::-1]
1494
- if d.dy < 0:
1495
- volume = volume[:, ::-1, :]
1496
- if d.dv < 0:
1497
- volume = volume[::-1, :, :]
1498
- for lev in levels:
1499
- if lev * sigma > np.max(volume):
1500
- continue
1501
- vertices, simplices, _, _ = measure.marching_cubes(volume, lev * sigma)
1502
- Xg, Yg, Zg = [t[0] + i * dt for t, i, dt
1503
- in zip(s, vertices.T[::-1], ds)]
1504
- match axis:
1505
- case 2:
1506
- Xg = Xg * 0 + (x[-1] if sign == 1 else x[0])
1507
- case 1:
1508
- Yg = Yg * 0 + (y[-1] if sign == 1 else y[0])
1509
- case 0:
1510
- Zg = Zg * 0 + (v[-1] if sign == 1 else v[0])
1511
- i, j, k = simplices.T
1512
- mesh2d = dict(type='mesh3d', x=Xg, y=Yg, z=Zg,
1513
- i=i, j=j, k=k,
1514
- intensity=Zg * 0 + lev,
1515
- colorscale=cmap, reversescale=False,
1516
- cmin=np.min(levels), cmax=np.max(levels),
1517
- opacity=alpha, name='', showscale=False)
1518
- data.append(mesh2d)
1519
-
1520
1523
  klist = [xplus, xminus, yplus, yminus, vplus, vminus]
1521
1524
  slist = [1, -1, 1, -1, 1, -1]
1522
1525
  alist = [2, 2, 1, 1, 0, 0]
1523
1526
  for kw, sign, axis in zip(klist, slist, alist):
1524
- plot_on_wall(sign=sign, axis=axis, **kw)
1527
+ _plot_on_wall(d, x, y, v, measure, data, sign, axis, **kw)
1525
1528
 
1526
1529
  if return_data_layout:
1527
1530
  return {'data': data, 'layout': layout}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotastrodata
3
- Version: 1.9.8
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