pymakeplots 0.2.1__py3-none-any.whl → 0.2.2__py3-none-any.whl

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.
@@ -12,8 +12,8 @@ from mpl_toolkits.axes_grid1 import make_axes_locatable
12
12
  from matplotlib.patches import Ellipse,Rectangle
13
13
  from matplotlib import cm
14
14
  from matplotlib.colors import ListedColormap, LinearSegmentedColormap
15
- from matplotlib.offsetbox import AnchoredText
16
- from mpl_toolkits.axes_grid1.anchored_artists import AnchoredEllipse,AnchoredSizeBar
15
+ from matplotlib.offsetbox import AnchoredText,AuxTransformBox, AnchoredOffsetbox
16
+ from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar
17
17
  from astropy.coordinates import ICRS
18
18
  import matplotlib.gridspec as gridspec
19
19
  from astropy.table import Table
@@ -23,6 +23,8 @@ import warnings
23
23
  from spectral_cube import SpectralCube
24
24
  from spectral_cube.utils import SpectralCubeWarning
25
25
  warnings.filterwarnings(action='ignore', category=SpectralCubeWarning, append=True)
26
+ from scipy.stats import mode
27
+
26
28
 
27
29
  def running_mean(x, N):
28
30
  cumsum = np.cumsum(np.insert(x, 0, 0))
@@ -38,7 +40,7 @@ def rotateImage(img, angle, pivot):
38
40
 
39
41
 
40
42
  class pymakeplots:
41
- def __init__(self,cube_flat=None,pb=None,cube=None):
43
+ def __init__(self,cube_flat=None,pb=None,cube=None,rest_value=None):
42
44
  self.galname=None
43
45
  self.gal_distance=None
44
46
  self.posang=None
@@ -88,24 +90,27 @@ class pymakeplots:
88
90
  self.flipped=False
89
91
  self.make_square=True
90
92
  self.useallpixels = False
93
+ self.suppress_subbeam_artifacts=False
91
94
  #self.wcs=None
92
95
 
93
96
  if (cube != None)&(pb==None)&(cube_flat==None):
94
97
  # only one cube given
95
- self.input_cube_nopb(cube)
98
+ self.input_cube_nopb(cube,rest_value=rest_value)
96
99
 
97
100
  if (cube != None)&(pb!=None):
98
101
  # pbcorred cube and pb given
99
- self.input_cube_pbcorr(cube,pb)
102
+ self.input_cube_pbcorr(cube,pb,rest_value=rest_value)
100
103
 
101
104
  if (cube_flat != None)&(pb!=None):
102
105
  # flat cube and pb given
103
106
  if np.any(self.pbcorr_cube) == None: #check if the user gave all three cubes, in which case this call is redundant
104
- self.input_cube_flat(cube_flat,pb)
107
+ self.input_cube_flat(cube_flat,pb,rest_value=rest_value)
105
108
 
106
109
  if (cube != None)&(pb==None)&(cube_flat!=None):
107
110
  # pbcorred cube and flat cube given
108
- self.input_cube_pbcorr_and_flat(cube,cube_flat)
111
+ self.input_cube_pbcorr_and_flat(cube,cube_flat,rest_value=rest_value)
112
+
113
+ self.cube_for_param_guesses=self.flat_cube
109
114
 
110
115
  def vsystrans_inv(self,val):
111
116
  return val +self.vsys
@@ -129,21 +134,21 @@ class pymakeplots:
129
134
  def beam_area(self):
130
135
  return (np.pi*(self.bmaj/self.cellsize)*(self.bmin/self.cellsize))/(4*np.log(2))
131
136
 
132
- def input_cube_pbcorr(self,path_to_pbcorr_cube,path_to_pb):
137
+ def input_cube_pbcorr(self,path_to_pbcorr_cube,path_to_pb,rest_value=None):
133
138
 
134
- self.pbcorr_cube = self.read_primary_cube(path_to_pbcorr_cube)
139
+ self.pbcorr_cube = self.read_primary_cube(path_to_pbcorr_cube,rest_value=rest_value)
135
140
 
136
- pb,hdr,_= self.read_in_a_cube(path_to_pb)
141
+ pb,hdr,_= self.read_in_a_cube(path_to_pb,rest_value=rest_value)
137
142
  if self.flipped: pb=np.flip(pb,axis=2)
138
143
 
139
144
  self.flat_cube = self.pbcorr_cube*pb
140
145
 
141
146
 
142
- def input_cube_flat(self,path_to_flat_cube,path_to_pb):
147
+ def input_cube_flat(self,path_to_flat_cube,path_to_pb,rest_value=None):
143
148
 
144
- self.flat_cube = self.read_primary_cube(path_to_flat_cube)
149
+ self.flat_cube = self.read_primary_cube(path_to_flat_cube,rest_value=rest_value)
145
150
 
146
- pb,hdr,_= self.read_in_a_cube(path_to_pb)
151
+ pb,hdr,_= self.read_in_a_cube(path_to_pb,rest_value=rest_value)
147
152
  if self.flipped: pb=np.flip(pb,axis=2)
148
153
 
149
154
  self.pbcorr_cube = self.flat_cube.copy()*0.0
@@ -151,25 +156,25 @@ class pymakeplots:
151
156
 
152
157
 
153
158
 
154
- def input_cube_nopb(self,path_to_cube):
159
+ def input_cube_nopb(self,path_to_cube,rest_value=None):
155
160
 
156
- self.pbcorr_cube = self.read_primary_cube(path_to_cube)
161
+ self.pbcorr_cube = self.read_primary_cube(path_to_cube,rest_value=rest_value)
157
162
 
158
163
  self.flat_cube = self.pbcorr_cube
159
164
 
160
165
 
161
166
 
162
- def input_cube_pbcorr_and_flat(self,path_to_pbcorr_cube,path_to_flat_cube):
167
+ def input_cube_pbcorr_and_flat(self,path_to_pbcorr_cube,path_to_flat_cube,rest_value=None):
163
168
 
164
- self.pbcorr_cube = self.read_primary_cube(path_to_pbcorr_cube)
169
+ self.pbcorr_cube = self.read_primary_cube(path_to_pbcorr_cube,rest_value=rest_value)
170
+
171
+ self.flat_cube,hdr,_ = self.read_in_a_cube(path_to_flat_cube,rest_value=rest_value)
165
172
 
166
- self.flat_cube,hdr,_ = self.read_in_a_cube(path_to_flat_cube)
167
173
  if self.flipped: self.flat_cube=np.flip(self.flat_cube,axis=2)
168
174
 
169
175
  def smooth_mask(self,cube):
170
176
  """
171
177
  Apply a Gaussian blur, using sigma = 4 in the velocity direction (seems to work best), to the uncorrected cube.
172
- The mode 'nearest' seems to give the best results.
173
178
  :return: (ndarray) mask to apply to the un-clipped cube
174
179
  """
175
180
  sigma = 1.5 * self.bmaj / self.cellsize
@@ -178,9 +183,14 @@ class pymakeplots:
178
183
  self.cliplevel=self.rms*self.rmsfac
179
184
  self.maskcliplevel=newrms*self.rmsfac
180
185
  mask=(smooth_cube > self.maskcliplevel)
181
- # print("Clip level:",((3e20*1.6014457E-20*91.9)/(self.bmaj*self.bmin))*self.cliplevel*self.dv)
182
- # import ipdb
183
- # ipdb.set_trace()
186
+
187
+ if self.suppress_subbeam_artifacts:
188
+ label,cnt=ndimage.label(mask)#.sum(axis=2))
189
+ hist,lab=np.histogram(label,bins=np.arange(cnt+1))
190
+ beampix=(self.bmaj*self.bmin)/(self.cellsize**2)
191
+ for thelabel in lab[0:-1][hist<(beampix*self.suppress_subbeam_artifacts)]:
192
+ mask[label == thelabel]=False
193
+
184
194
  return mask
185
195
 
186
196
 
@@ -322,34 +332,37 @@ class pymakeplots:
322
332
 
323
333
  return x1,y1,v1,np.abs(cd1),cd3
324
334
 
325
- def read_in_a_cube(self,path):
326
- self.spectralcube=SpectralCube.read(path).with_spectral_unit(u.km/u.s, velocity_convention='radio')#, rest_value=self.restfreq)
335
+ def read_in_a_cube(self,path,rest_value=None,primary=False):
336
+
337
+ scube=SpectralCube.read(path).with_spectral_unit(u.km/u.s, velocity_convention='radio',rest_value=rest_value)
327
338
 
328
- hdr=self.spectralcube.header
329
- cube = np.squeeze(self.spectralcube.filled_data[:,:,:].T).value #squeeze to remove singular stokes axis if present
339
+ hdr=scube.header
340
+ cube = np.squeeze(scube.filled_data[:,:,:].T).value #squeeze to remove singular stokes axis if present
330
341
  cube[np.isfinite(cube) == False] = 0.0
331
342
  try:
332
- beamtab=self.spectralcube.beam
343
+ beamtab=scube.beam
333
344
  except:
334
345
  try:
335
- beamtab=self.spectralcube.beams[np.floor(self.spectralcube.beams.size/2).astype(int)]
346
+ beamtab=scube.beams[np.floor(scube.beams.size/2).astype(int)]
336
347
  except:
337
348
  #try flipping them
338
349
  try:
339
- beamvals=[self.spectralcube.header['bmaj'],self.spectralcube.header['bmin']]
350
+ beamvals=[scube.header['bmaj'],scube.header['bmin']]
340
351
  beamtab=Beam(major=np.max(beamvals)*u.deg,minor=np.min(beamvals)*u.deg,pa=self.spectralcube.header['bpa']*u.deg)
341
352
  except:
342
- beamtab=False
343
- self.repfreq=np.median(self.spectralcube.with_spectral_unit(u.GHz).spectral_axis)
353
+ beamtab=False
354
+ if primary:
355
+ self.spectralcube=scube
356
+ self.repfreq=np.median(self.spectralcube.with_spectral_unit(u.GHz).spectral_axis)
344
357
  return cube, hdr, beamtab
345
358
 
346
359
 
347
360
 
348
- def read_primary_cube(self,cube):
361
+ def read_primary_cube(self,cube,rest_value=None):
349
362
 
350
363
  ### read in cube ###
351
- datacube,hdr,beam = self.read_in_a_cube(cube)
352
-
364
+ datacube,hdr,beam = self.read_in_a_cube(cube,rest_value=rest_value,primary=True)
365
+
353
366
  self.bmaj=beam.major.to(u.arcsec).value
354
367
  self.bmin=beam.minor.to(u.arcsec).value
355
368
  self.bpa=beam.pa.value
@@ -359,15 +372,9 @@ class pymakeplots:
359
372
  self.galname=hdr['OBJECT']
360
373
  except:
361
374
  self.galname="Galaxy"
362
-
363
-
364
-
375
+
365
376
  self.xcoord,self.ycoord,self.vcoord,self.cellsize,self.dv = self.get_header_coord_arrays(hdr)
366
- #breakpoint()
367
-
368
-
369
377
 
370
-
371
378
  if self.dv < 0:
372
379
  datacube = np.flip(datacube,axis=2)
373
380
  self.dv*=(-1)
@@ -475,7 +482,6 @@ class pymakeplots:
475
482
  y2 = s*xpv + c*ypv
476
483
  ax2.scatter(0,0,facecolors='none',edgecolors='k')
477
484
  ax2.plot(x2,y2,'k--')
478
- #breakpoint()
479
485
 
480
486
  ###### make summary box
481
487
 
@@ -503,6 +509,7 @@ class pymakeplots:
503
509
 
504
510
  if pdf:
505
511
  plt.savefig(self.galname+"_allplots.pdf", bbox_inches = 'tight')
512
+ plt.close()
506
513
  else:
507
514
  plt.show()
508
515
 
@@ -586,19 +593,27 @@ class pymakeplots:
586
593
 
587
594
 
588
595
 
589
- if self.chans2do == None:
590
- # use the mask to try and guess the channels with signal.
591
- mask_cumsum=np.nancumsum((self.pbcorr_cube > self.rmsfac*self.rms).sum(axis=0).sum(axis=0))
592
- w_low,=np.where(mask_cumsum/np.max(mask_cumsum) < 0.02)
593
- w_high,=np.where(mask_cumsum/np.max(mask_cumsum) > 0.98)
596
+ if np.any(self.chans2do == None):
594
597
 
595
- if w_low.size ==0: w_low=np.array([0])
596
- if w_high.size ==0: w_high=np.array([self.vcoord.size])
597
- self.chans2do=[np.clip(np.max(w_low)-2,0,self.vcoord.size),np.clip(np.min(w_high)+2,0,self.vcoord.size)]
598
-
598
+ clip=4.0
599
+ vwidth=4000
600
+ while vwidth > 1500:
601
+ clip+=0.1
602
+ # use the mask to try and guess the channels with signal.
603
+ mask_cumsum=np.nancumsum((self.cube_for_param_guesses > clip*self.rms).sum(axis=0).sum(axis=0))
604
+ w_low,=np.where(mask_cumsum/np.nanmax(mask_cumsum) < 0.05)
605
+ w_high,=np.where(mask_cumsum/np.nanmax(mask_cumsum) > 0.95)
606
+
607
+ if w_low.size ==0: w_low=np.array([0])
608
+ if w_high.size ==0: w_high=np.array([self.vcoord.size])
609
+ #breakpoint()
610
+ self.chans2do=[np.clip(np.max(w_low)-7,0,self.vcoord.size-1),np.clip(np.min(w_high)+7,0,self.vcoord.size-1)]
611
+ vwidth=self.vcoord[self.chans2do[1]]-self.vcoord[self.chans2do[0]]
612
+ #print(clip)
613
+
599
614
  if self.vsys == None:
600
615
  # use the cube to try and guess the vsys
601
- self.vsys=((self.pbcorr_cube*(self.pbcorr_cube > self.rmsfac*self.rms)).sum(axis=0).sum(axis=0)*self.vcoord).sum()/((self.pbcorr_cube*(self.pbcorr_cube > self.rmsfac*self.rms)).sum(axis=0).sum(axis=0)).sum()
616
+ self.vsys=((self.cube_for_param_guesses*(self.cube_for_param_guesses > self.rmsfac*self.rms)).sum(axis=0).sum(axis=0)*self.vcoord).sum()/((self.cube_for_param_guesses*(self.cube_for_param_guesses > self.rmsfac*self.rms)).sum(axis=0).sum(axis=0)).sum()
602
617
 
603
618
  if self.imagesize != None:
604
619
  if np.array(self.imagesize).size == 1:
@@ -612,7 +627,7 @@ class pymakeplots:
612
627
 
613
628
  if self.spatial_trim == None:
614
629
 
615
- mom0=(self.pbcorr_cube > self.rmsfac*self.rms).sum(axis=2)
630
+ mom0=(self.cube_for_param_guesses > self.rmsfac*self.rms).sum(axis=2)
616
631
  mom0[mom0>0]=1
617
632
 
618
633
  cumulative_x = np.nancumsum(mom0.sum(axis=1),dtype=float)
@@ -662,19 +677,16 @@ class pymakeplots:
662
677
  return cb
663
678
 
664
679
 
665
- def add_beam(self,ax):
680
+ def add_beam(self,ax):
681
+ aux_tr_box = AuxTransformBox(ax.transData)
682
+
666
683
  if self.all_axes_physical:
667
- ae = AnchoredEllipse(ax.transData, width=self.ang2kpctrans(self.bmaj), height=self.ang2kpctrans(self.bmin), angle=self.bpa+90,
668
- loc='lower left', pad=0.5, borderpad=0.4,
669
- frameon=False)
684
+ aux_tr_box.add_artist(Ellipse((0, 0), width=self.ang2kpctrans(self.bmaj), height=self.ang2kpctrans(self.bmin), angle=self.bpa+90,edgecolor='black',facecolor='none',linewidth=1.5))
670
685
  else:
671
- ae = AnchoredEllipse(ax.transData, width=self.bmaj, height=self.bmin, angle=self.bpa+90,
672
- loc='lower left', pad=0.5, borderpad=0.4,
673
- frameon=False)
674
- ae.ellipse.set_edgecolor('black')
675
- ae.ellipse.set_facecolor('none')
676
- ae.ellipse.set_linewidth(1.5)
677
- ax.add_artist(ae)
686
+ aux_tr_box.add_artist(Ellipse((0, 0), width=self.bmaj, height=self.bmin, angle=self.bpa+90,edgecolor='black',facecolor='none',linewidth=1.5))
687
+ box = AnchoredOffsetbox(child=aux_tr_box, loc='lower left', pad=0.5, borderpad=0.4,frameon=False)
688
+ ax.add_artist(box)
689
+
678
690
 
679
691
 
680
692
 
@@ -819,12 +831,13 @@ class pymakeplots:
819
831
  mom2[i,j]=np.sqrt(np.sum(np.abs(self.pbcorr_cube_trim[i,j,:]*self.mask_trim[i,j,:]) * (self.vcoord_trim - mom1[i,j]) ** 2, axis=0) / np.sum(abs(self.pbcorr_cube_trim[i,j]*self.mask_trim[i,j,:]), axis=0))
820
832
 
821
833
  if self.maxvdisp == None:
822
- self.maxvdisp=np.ceil(np.clip(np.nanstd(mom2)*4,0,np.nanmax(mom2))/10.)*10.
823
-
824
-
825
-
834
+ self.maxvdisp=np.ceil(np.clip(np.nanstd(mom2)*4,20,np.nanmax(mom2))/10.)*10.
835
+ else:
836
+ self.maxvdisp=np.ceil(np.clip(np.nanstd(mom2)*4,20,self.maxvdisp)/10.)*10.
837
+ if np.isfinite(self.maxvdisp)==False:
838
+ self.maxvdisp=50.
839
+ #breakpoint()
826
840
  mom2levs=np.linspace(0,self.maxvdisp,10)
827
-
828
841
  im1=ax1.contourf(self.xc,self.yc,mom2.T,levels=mom2levs,cmap=sauron,vmax=self.maxvdisp)
829
842
 
830
843
  if self.all_axes_physical:
@@ -844,7 +857,7 @@ class pymakeplots:
844
857
  vticks=np.arange(0,5)*dvticks
845
858
 
846
859
  cb=self.colorbar(im1,ticks=vticks)
847
- cb.set_label("$\sigma_{obs}$ (km s$^{-1}$)")
860
+ cb.set_label('$\\sigma_{obs}$ (km s$^{-1}$)')
848
861
 
849
862
 
850
863
  self.add_beam(ax1)
@@ -969,32 +982,67 @@ class pymakeplots:
969
982
  if self.posang==None:
970
983
  # try fitting the moment one to get the kinematic pa
971
984
  if not self.silent: print("No position angle given, estimating using the observed moment one.")
972
- mom0=(self.pbcorr_cube_trim*self.mask_trim).sum(axis=2)
985
+ mom0=(self.flat_cube_trim*self.mask_trim).sum(axis=2)
973
986
  mom1=mom0.copy()*np.nan
974
- mom1[mom0 != 0.0] = (((self.pbcorr_cube_trim*self.mask_trim)*self.vcoord_trim).sum(axis=2))[mom0 != 0.0]/mom0[mom0 != 0.0]
975
- mom1=mom1.T
987
+ mom1[mom0 != 0.0] = (((self.flat_cube_trim*self.mask_trim)*self.vcoord_trim).sum(axis=2))[mom0 != 0.0]/mom0[mom0 != 0.0]
988
+ mom1=mom1.T
976
989
 
977
-
990
+ # ### sigma clip
991
+ # mom1[np.abs(mom1/np.nanstd(mom1))>5]=np.nan
992
+
993
+ ### select largest contigious structure
994
+ label,cnt=ndimage.label(self.mask_trim.sum(axis=2))
995
+ mode_label= mode(label[label>0])
996
+
997
+ hist,lab=np.histogram(label[label>0],bins=np.arange(cnt+1)+1)
998
+ beampix=(self.bmaj*self.bmin)/(self.cellsize**2)
999
+
1000
+
1001
+ if len(lab[0:-1][hist<beampix]) != len(lab[0:-1]):
1002
+
1003
+ ## remove beam size artifacts
1004
+ for thelabel in lab[0:-1][hist<beampix]:
1005
+ mom1[label.T == thelabel]=np.nan
1006
+
1007
+ ## keep biggest structures that contain >80% of remaining pixels
1008
+ remainlab=lab[0:-1][hist>beampix]
1009
+ remainhist=hist[hist>beampix]
1010
+ st=np.argsort(remainhist)
1011
+ for thelabel in remainlab[st][np.nancumsum(remainhist[st]/np.sum(remainhist)) < 0.2]:
1012
+ mom1[label.T == thelabel]=np.nan
1013
+
1014
+ else:
1015
+ mom1[label.T != mode_label.mode]=np.nan
1016
+
1017
+ #self.useallpixels=True
1018
+
1019
+ ### remove median
1020
+ mom1-=np.nanmedian(mom1)
1021
+
1022
+
1023
+
1024
+ #breakpoint()
978
1025
  # if the cube is small, use it directly to estimate posang. If its large, then interpolate down to keep runtime low.
979
- if (self.pbcorr_cube_trim[:,:,0].size < 50*50) or (self.useallpixels):
980
- xv, yv = np.meshgrid(self.xc,self.yc)
981
- x,y,v = xv[np.isfinite(mom1)],yv[np.isfinite(mom1)],mom1[np.isfinite(mom1)]
982
- else:
983
- print("Downsampling the observed moment one in PA estimate for speed. Set `useallpixels` to override.")
984
- mom1[np.isfinite(mom1) == False] = self.vsys
985
- #breakpoint()
986
- interper = interpolate.RegularGridInterpolator((self.xc,self.yc),(mom1-self.vsys).T,bounds_error=False,fill_value=np.nan)
987
- x=np.linspace(np.min(self.xc),np.max(self.xc),50)
988
- y=np.linspace(np.min(self.yc),np.max(self.yc),50)
989
- xv, yv = np.meshgrid(x,y)
990
- v= interper((xv,yv))
991
- x,y,v = xv.flatten(),yv.flatten(),v.flatten()
992
-
993
- self.posang,_,_ = fit_kinematic_pa(x[np.isfinite(v)],y[np.isfinite(v)],v[np.isfinite(v)],nsteps=36,plot=False,quiet=True)
1026
+ # if (self.pbcorr_cube_trim[:,:,0].size < 50*50) or (self.useallpixels):
1027
+ xv, yv = np.meshgrid(self.xc,self.yc)
1028
+ x,y,v = xv[np.isfinite(mom1)],yv[np.isfinite(mom1)],mom1[np.isfinite(mom1)]
1029
+ # else:
1030
+ # print("Downsampling the observed moment one in PA estimate for speed. Set `useallpixels` to override.")
1031
+ #mom1[np.isfinite(mom1) == False] = self.vsys
1032
+ #breakpoint()
1033
+ # interper = interpolate.RegularGridInterpolator((self.xc,self.yc),(mom1-self.vsys).T,bounds_error=False,fill_value=np.nan)
1034
+ # x=np.linspace(np.min(self.xc),np.max(self.xc),self.xc.size//2)
1035
+ # y=np.linspace(np.min(self.yc),np.max(self.yc),self.yc.size//2)
1036
+ # xv, yv = np.meshgrid(x,y)
1037
+ # v= interper((xv,yv))
1038
+ # x,y,v = xv.flatten(),yv.flatten(),v.flatten()
994
1039
 
1040
+ #breakpoint()
1041
+ self.posang,_,_ = fit_kinematic_pa(x[np.isfinite(v)],y[np.isfinite(v)],v[np.isfinite(v)],nsteps=36,plot=False,quiet=True)
1042
+
995
1043
  if np.sin(np.deg2rad((self.posang+45)*2)) > 0:
996
1044
  # do y axis cut
997
- if np.nanmean(mom1[self.yc > 0,:]) > np.nanmean(mom1[self.yc < 0,:]):
1045
+ if np.nansum(mom1[self.yc > 0,:])/(mom1[self.yc > 0,:]).size > np.nansum(mom1[self.yc < 0,:])/(mom1[self.yc < 0,:]).size:
998
1046
  # posang should be gt 180
999
1047
  if self.posang < 180: self.posang += 180
1000
1048
  else:
@@ -1002,15 +1050,14 @@ class pymakeplots:
1002
1050
  if self.posang > 180: self.posang -= 180
1003
1051
  else:
1004
1052
  # do x axis cut
1005
- if np.nanmean(mom1[:,self.xc > 0]) > np.nanmean(mom1[:,self.xc < 0]):
1053
+ if np.nansum(mom1[:,self.xc > 0])/(mom1[:,self.xc > 0]).size > np.nansum(mom1[:,self.xc < 0])/(mom1[:,self.xc < 0]).size:
1006
1054
  # posang should be gt 180
1007
1055
  if self.posang < 180: self.posang += 180
1008
1056
  else:
1009
1057
  # posang should be lt 180
1010
1058
  if self.posang > 180: self.posang -= 180
1011
1059
  if not self.silent: print("PA estimate (degrees): ",np.round(self.posang,1))
1012
-
1013
-
1060
+
1014
1061
  centpix_x=np.where(np.isclose(self.xc,0.0,atol=self.cellsize/1.9))[0]
1015
1062
  centpix_y=np.where(np.isclose(self.yc,0.0,atol=self.cellsize/1.9))[0]
1016
1063
 
@@ -1047,9 +1094,15 @@ class pymakeplots:
1047
1094
  newcmp = ListedColormap(oldcmp(np.linspace(0.15, 1, 256)))
1048
1095
 
1049
1096
 
1097
+ if np.nanmax(pvd) < self.cliplevel:
1098
+ contour_levels=np.linspace(np.nanmax(pvd)/2.,np.nanmax(pvd),10)
1099
+ if np.sum(contour_levels)==0:
1100
+ contour_levels=np.array([self.cliplevel,self.cliplevel+0.1])
1101
+ else:
1102
+ contour_levels=np.linspace(self.cliplevel,np.nanmax(pvd),10)
1050
1103
 
1051
- axes.contourf(pvdaxis,vaxis,pvd.T,levels=np.linspace(self.cliplevel,np.nanmax(pvd),10),cmap=newcmp)
1052
- axes.contour(pvdaxis,vaxis,pvd.T,levels=np.linspace(self.cliplevel,np.nanmax(pvd),10),colors='black')
1104
+ axes.contourf(pvdaxis,vaxis,pvd.T,levels=contour_levels,cmap=newcmp)
1105
+ axes.contour(pvdaxis,vaxis,pvd.T,levels=contour_levels,colors='black')
1053
1106
 
1054
1107
  if self.all_axes_physical:
1055
1108
  axes.set_xlabel('Offset (kpc)')
@@ -1067,7 +1120,7 @@ class pymakeplots:
1067
1120
  secax = axes.secondary_yaxis('right', functions=(self.vsystrans, self.vsystrans_inv))
1068
1121
  secax.set_ylabel(r'V$_{\rm offset}$ (km s$^{-1}$)')
1069
1122
 
1070
- anchored_text = AnchoredText("PA: "+str(round(self.posang,1))+"$^{\circ}$", loc=loc1,frameon=False)
1123
+ anchored_text = AnchoredText("PA: "+str(round(self.posang,1))+'$^{\\circ}$', loc=loc1,frameon=False)
1071
1124
  axes.add_artist(anchored_text)
1072
1125
 
1073
1126
  if self.gal_distance != None and not self.all_axes_physical:
@@ -1078,6 +1131,7 @@ class pymakeplots:
1078
1131
 
1079
1132
  if pdf:
1080
1133
  plt.savefig(self.galname+"_pvd.pdf", bbox_inches = 'tight')
1134
+ plt.close()
1081
1135
  else:
1082
1136
  if not outsideaxis: plt.show()
1083
1137
 
@@ -1149,6 +1203,7 @@ class pymakeplots:
1149
1203
 
1150
1204
  if pdf:
1151
1205
  plt.savefig(self.galname+"_spec.pdf", bbox_inches = 'tight')
1206
+ plt.close()
1152
1207
  else:
1153
1208
  if not outsideaxis: plt.show()
1154
1209
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymakeplots
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Home-page: https://github.com/TimothyADavis/pymakeplots
5
5
  Author: Timothy A. Davis
6
6
  Author-email: DavisT@cardiff.ac.uk
@@ -0,0 +1,9 @@
1
+ pymakeplots/__init__.py,sha256=PLKnIm6rIKYjH_b6L9UBCFtv1lKt5GItdBKDbSOhuMU,87
2
+ pymakeplots/pymakeplots.py,sha256=_N8Wp2teEfr6W9SqBi3bb2WV3F7vxzfVhWDnhq_Qa1E,48843
3
+ pymakeplots/sauron_colormap.py,sha256=8APka-_L432wyICcHcySjk3qmjNOynb3iDjjlMuUTU0,4448
4
+ pymakeplots-0.2.2.dist-info/LICENSE.md,sha256=qtvmvajOPCad_5HMY5u49hldzBIXz7tbHbuGSG_HE5o,1077
5
+ pymakeplots-0.2.2.dist-info/METADATA,sha256=YlzzxZMuONkCuzkhi_5tHinfu6TsqW8MzdpB5jG_QTg,1847
6
+ pymakeplots-0.2.2.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
7
+ pymakeplots-0.2.2.dist-info/top_level.txt,sha256=KgG17vI_D6BsiKRe_81UU5709tXc6Ha7gx1IwjA7ur8,12
8
+ pymakeplots-0.2.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
9
+ pymakeplots-0.2.2.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- pymakeplots/__init__.py,sha256=PLKnIm6rIKYjH_b6L9UBCFtv1lKt5GItdBKDbSOhuMU,87
2
- pymakeplots/pymakeplots.py,sha256=EIeZH1brAg5d9QM9QqaViXFBBDDVCRDWnK1hKZ6ofXg,45950
3
- pymakeplots/sauron_colormap.py,sha256=8APka-_L432wyICcHcySjk3qmjNOynb3iDjjlMuUTU0,4448
4
- pymakeplots-0.2.1.dist-info/LICENSE.md,sha256=qtvmvajOPCad_5HMY5u49hldzBIXz7tbHbuGSG_HE5o,1077
5
- pymakeplots-0.2.1.dist-info/METADATA,sha256=GGL0jJnyhIuv9bmggds2jNoWRTPbXyPU-cQ4jlJJ_3M,1847
6
- pymakeplots-0.2.1.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
7
- pymakeplots-0.2.1.dist-info/top_level.txt,sha256=KgG17vI_D6BsiKRe_81UU5709tXc6Ha7gx1IwjA7ur8,12
8
- pymakeplots-0.2.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
9
- pymakeplots-0.2.1.dist-info/RECORD,,