pymakeplots 0.2.1__tar.gz → 0.2.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymakeplots
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Home-page: https://github.com/TimothyADavis/pymakeplots
5
5
  Author: Timothy A. Davis
6
6
  Author-email: DavisT@cardiff.ac.uk
@@ -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,velocity_convention='radio'):
42
44
  self.galname=None
43
45
  self.gal_distance=None
44
46
  self.posang=None
@@ -56,6 +58,7 @@ class pymakeplots:
56
58
  self.pbcorr_cube_trim=None
57
59
  self.mask_trim=None
58
60
  self.bmaj=None
61
+ self.smoothmask_spatial=1.5
59
62
  self.bmin=None
60
63
  self.bpa=None
61
64
  self.xcoord,self.ycoord,self.vcoord = None, None, None
@@ -65,6 +68,7 @@ class pymakeplots:
65
68
  self.silent=False # rig for silent running if true
66
69
  self.bardist=None
67
70
  self.rmsfac=3
71
+ self.velocity_convention=velocity_convention
68
72
  self.restfreq=None
69
73
  self.repfreq=None
70
74
  self.obj_ra=None
@@ -88,24 +92,27 @@ class pymakeplots:
88
92
  self.flipped=False
89
93
  self.make_square=True
90
94
  self.useallpixels = False
95
+ self.suppress_subbeam_artifacts=False
91
96
  #self.wcs=None
92
97
 
93
98
  if (cube != None)&(pb==None)&(cube_flat==None):
94
99
  # only one cube given
95
- self.input_cube_nopb(cube)
100
+ self.input_cube_nopb(cube,rest_value=rest_value)
96
101
 
97
102
  if (cube != None)&(pb!=None):
98
103
  # pbcorred cube and pb given
99
- self.input_cube_pbcorr(cube,pb)
104
+ self.input_cube_pbcorr(cube,pb,rest_value=rest_value)
100
105
 
101
106
  if (cube_flat != None)&(pb!=None):
102
107
  # flat cube and pb given
103
- 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)
108
+ if np.any(self.pbcorr_cube == None): #check if the user gave all three cubes, in which case this call is redundant
109
+ self.input_cube_flat(cube_flat,pb,rest_value=rest_value)
105
110
 
106
111
  if (cube != None)&(pb==None)&(cube_flat!=None):
107
112
  # pbcorred cube and flat cube given
108
- self.input_cube_pbcorr_and_flat(cube,cube_flat)
113
+ self.input_cube_pbcorr_and_flat(cube,cube_flat,rest_value=rest_value)
114
+
115
+ self.cube_for_param_guesses=self.flat_cube
109
116
 
110
117
  def vsystrans_inv(self,val):
111
118
  return val +self.vsys
@@ -129,21 +136,21 @@ class pymakeplots:
129
136
  def beam_area(self):
130
137
  return (np.pi*(self.bmaj/self.cellsize)*(self.bmin/self.cellsize))/(4*np.log(2))
131
138
 
132
- def input_cube_pbcorr(self,path_to_pbcorr_cube,path_to_pb):
139
+ def input_cube_pbcorr(self,path_to_pbcorr_cube,path_to_pb,rest_value=None):
133
140
 
134
- self.pbcorr_cube = self.read_primary_cube(path_to_pbcorr_cube)
141
+ self.pbcorr_cube = self.read_primary_cube(path_to_pbcorr_cube,rest_value=rest_value)
135
142
 
136
- pb,hdr,_= self.read_in_a_cube(path_to_pb)
143
+ pb,hdr,_= self.read_in_a_cube(path_to_pb,rest_value=rest_value)
137
144
  if self.flipped: pb=np.flip(pb,axis=2)
138
145
 
139
146
  self.flat_cube = self.pbcorr_cube*pb
140
147
 
141
148
 
142
- def input_cube_flat(self,path_to_flat_cube,path_to_pb):
149
+ def input_cube_flat(self,path_to_flat_cube,path_to_pb,rest_value=None):
143
150
 
144
- self.flat_cube = self.read_primary_cube(path_to_flat_cube)
151
+ self.flat_cube = self.read_primary_cube(path_to_flat_cube,rest_value=rest_value)
145
152
 
146
- pb,hdr,_= self.read_in_a_cube(path_to_pb)
153
+ pb,hdr,_= self.read_in_a_cube(path_to_pb,rest_value=rest_value)
147
154
  if self.flipped: pb=np.flip(pb,axis=2)
148
155
 
149
156
  self.pbcorr_cube = self.flat_cube.copy()*0.0
@@ -151,36 +158,41 @@ class pymakeplots:
151
158
 
152
159
 
153
160
 
154
- def input_cube_nopb(self,path_to_cube):
161
+ def input_cube_nopb(self,path_to_cube,rest_value=None):
155
162
 
156
- self.pbcorr_cube = self.read_primary_cube(path_to_cube)
163
+ self.pbcorr_cube = self.read_primary_cube(path_to_cube,rest_value=rest_value)
157
164
 
158
165
  self.flat_cube = self.pbcorr_cube
159
166
 
160
167
 
161
168
 
162
- def input_cube_pbcorr_and_flat(self,path_to_pbcorr_cube,path_to_flat_cube):
169
+ def input_cube_pbcorr_and_flat(self,path_to_pbcorr_cube,path_to_flat_cube,rest_value=None):
163
170
 
164
- self.pbcorr_cube = self.read_primary_cube(path_to_pbcorr_cube)
171
+ self.pbcorr_cube = self.read_primary_cube(path_to_pbcorr_cube,rest_value=rest_value)
172
+
173
+ self.flat_cube,hdr,_ = self.read_in_a_cube(path_to_flat_cube,rest_value=rest_value)
165
174
 
166
- self.flat_cube,hdr,_ = self.read_in_a_cube(path_to_flat_cube)
167
175
  if self.flipped: self.flat_cube=np.flip(self.flat_cube,axis=2)
168
176
 
169
177
  def smooth_mask(self,cube):
170
178
  """
171
179
  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
180
  :return: (ndarray) mask to apply to the un-clipped cube
174
181
  """
175
- sigma = 1.5 * self.bmaj / self.cellsize
182
+ sigma = self.smoothmask_spatial * self.bmaj / self.cellsize
176
183
  smooth_cube = ndimage.uniform_filter(cube, size=[sigma, sigma,4], mode='constant') # mode='nearest'
177
184
  newrms= self.rms_estimate(smooth_cube,0,1)
178
185
  self.cliplevel=self.rms*self.rmsfac
179
186
  self.maskcliplevel=newrms*self.rmsfac
180
187
  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()
188
+
189
+ if self.suppress_subbeam_artifacts:
190
+ label,cnt=ndimage.label(mask)#.sum(axis=2))
191
+ hist,lab=np.histogram(label,bins=np.arange(cnt+1))
192
+ beampix=(self.bmaj*self.bmin)/(self.cellsize**2)
193
+ for thelabel in lab[0:-1][hist<(beampix*self.suppress_subbeam_artifacts)]:
194
+ mask[label == thelabel]=False
195
+
184
196
  return mask
185
197
 
186
198
 
@@ -322,34 +334,37 @@ class pymakeplots:
322
334
 
323
335
  return x1,y1,v1,np.abs(cd1),cd3
324
336
 
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)
337
+ def read_in_a_cube(self,path,rest_value=None,primary=False):
338
+
339
+ scube=SpectralCube.read(path).with_spectral_unit(u.km/u.s, velocity_convention=self.velocity_convention,rest_value=rest_value)
327
340
 
328
- hdr=self.spectralcube.header
329
- cube = np.squeeze(self.spectralcube.filled_data[:,:,:].T).value #squeeze to remove singular stokes axis if present
341
+ hdr=scube.header
342
+ cube = np.squeeze(scube.filled_data[:,:,:].T).value #squeeze to remove singular stokes axis if present
330
343
  cube[np.isfinite(cube) == False] = 0.0
331
344
  try:
332
- beamtab=self.spectralcube.beam
345
+ beamtab=scube.beam
333
346
  except:
334
347
  try:
335
- beamtab=self.spectralcube.beams[np.floor(self.spectralcube.beams.size/2).astype(int)]
348
+ beamtab=scube.beams[np.floor(scube.beams.size/2).astype(int)]
336
349
  except:
337
350
  #try flipping them
338
351
  try:
339
- beamvals=[self.spectralcube.header['bmaj'],self.spectralcube.header['bmin']]
352
+ beamvals=[scube.header['bmaj'],scube.header['bmin']]
340
353
  beamtab=Beam(major=np.max(beamvals)*u.deg,minor=np.min(beamvals)*u.deg,pa=self.spectralcube.header['bpa']*u.deg)
341
354
  except:
342
- beamtab=False
343
- self.repfreq=np.median(self.spectralcube.with_spectral_unit(u.GHz).spectral_axis)
355
+ beamtab=False
356
+ if primary:
357
+ self.spectralcube=scube
358
+ self.repfreq=np.median(self.spectralcube.with_spectral_unit(u.GHz).spectral_axis)
344
359
  return cube, hdr, beamtab
345
360
 
346
361
 
347
362
 
348
- def read_primary_cube(self,cube):
363
+ def read_primary_cube(self,cube,rest_value=None):
349
364
 
350
365
  ### read in cube ###
351
- datacube,hdr,beam = self.read_in_a_cube(cube)
352
-
366
+ datacube,hdr,beam = self.read_in_a_cube(cube,rest_value=rest_value,primary=True)
367
+
353
368
  self.bmaj=beam.major.to(u.arcsec).value
354
369
  self.bmin=beam.minor.to(u.arcsec).value
355
370
  self.bpa=beam.pa.value
@@ -359,15 +374,9 @@ class pymakeplots:
359
374
  self.galname=hdr['OBJECT']
360
375
  except:
361
376
  self.galname="Galaxy"
362
-
363
-
364
-
377
+
365
378
  self.xcoord,self.ycoord,self.vcoord,self.cellsize,self.dv = self.get_header_coord_arrays(hdr)
366
- #breakpoint()
367
-
368
-
369
379
 
370
-
371
380
  if self.dv < 0:
372
381
  datacube = np.flip(datacube,axis=2)
373
382
  self.dv*=(-1)
@@ -475,7 +484,6 @@ class pymakeplots:
475
484
  y2 = s*xpv + c*ypv
476
485
  ax2.scatter(0,0,facecolors='none',edgecolors='k')
477
486
  ax2.plot(x2,y2,'k--')
478
- #breakpoint()
479
487
 
480
488
  ###### make summary box
481
489
 
@@ -503,6 +511,7 @@ class pymakeplots:
503
511
 
504
512
  if pdf:
505
513
  plt.savefig(self.galname+"_allplots.pdf", bbox_inches = 'tight')
514
+ plt.close()
506
515
  else:
507
516
  plt.show()
508
517
 
@@ -512,14 +521,14 @@ class pymakeplots:
512
521
  def make_moments(self,axes=None,mom=[0,1,2],pdf=False,fits=False):
513
522
  mom=np.array(mom)
514
523
  self.fits=fits
515
-
516
- if np.any(self.xc) == None:
524
+
525
+ if np.any(self.xc == None):
517
526
  self.prepare_cubes()
518
527
 
519
528
  self.set_rc_params()
520
529
 
521
530
  nplots=mom.size
522
- if np.any(axes) == None:
531
+ if np.any(axes == None):
523
532
  if self.make_square:
524
533
  fig,axes=plt.subplots(1,nplots,sharey=True,figsize=(7*nplots,7), gridspec_kw = {'wspace':0, 'hspace':0})
525
534
  else:
@@ -586,19 +595,27 @@ class pymakeplots:
586
595
 
587
596
 
588
597
 
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)
598
+ if np.any(self.chans2do == None):
594
599
 
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
-
600
+ clip=4.0
601
+ vwidth=4000
602
+ while vwidth > 1500:
603
+ clip+=0.1
604
+ # use the mask to try and guess the channels with signal.
605
+ mask_cumsum=np.nancumsum((self.cube_for_param_guesses > clip*self.rms).sum(axis=0).sum(axis=0))
606
+ w_low,=np.where(mask_cumsum/np.nanmax(mask_cumsum) < 0.05)
607
+ w_high,=np.where(mask_cumsum/np.nanmax(mask_cumsum) > 0.95)
608
+
609
+ if w_low.size ==0: w_low=np.array([0])
610
+ if w_high.size ==0: w_high=np.array([self.vcoord.size])
611
+ #breakpoint()
612
+ 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)]
613
+ vwidth=self.vcoord[self.chans2do[1]]-self.vcoord[self.chans2do[0]]
614
+ #print(clip)
615
+
599
616
  if self.vsys == None:
600
617
  # 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()
618
+ 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
619
 
603
620
  if self.imagesize != None:
604
621
  if np.array(self.imagesize).size == 1:
@@ -612,7 +629,7 @@ class pymakeplots:
612
629
 
613
630
  if self.spatial_trim == None:
614
631
 
615
- mom0=(self.pbcorr_cube > self.rmsfac*self.rms).sum(axis=2)
632
+ mom0=(self.cube_for_param_guesses > self.rmsfac*self.rms).sum(axis=2)
616
633
  mom0[mom0>0]=1
617
634
 
618
635
  cumulative_x = np.nancumsum(mom0.sum(axis=1),dtype=float)
@@ -662,19 +679,16 @@ class pymakeplots:
662
679
  return cb
663
680
 
664
681
 
665
- def add_beam(self,ax):
682
+ def add_beam(self,ax):
683
+ aux_tr_box = AuxTransformBox(ax.transData)
684
+
666
685
  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)
686
+ 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
687
  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)
688
+ 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))
689
+ box = AnchoredOffsetbox(child=aux_tr_box, loc='lower left', pad=0.5, borderpad=0.4,frameon=False)
690
+ ax.add_artist(box)
691
+
678
692
 
679
693
 
680
694
 
@@ -819,12 +833,13 @@ class pymakeplots:
819
833
  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
834
 
821
835
  if self.maxvdisp == None:
822
- self.maxvdisp=np.ceil(np.clip(np.nanstd(mom2)*4,0,np.nanmax(mom2))/10.)*10.
823
-
824
-
825
-
836
+ self.maxvdisp=np.ceil(np.clip(np.nanstd(mom2)*4,20,np.nanmax(mom2))/10.)*10.
837
+ else:
838
+ self.maxvdisp=np.ceil(np.clip(np.nanstd(mom2)*4,20,self.maxvdisp)/10.)*10.
839
+ if np.isfinite(self.maxvdisp)==False:
840
+ self.maxvdisp=50.
841
+ #breakpoint()
826
842
  mom2levs=np.linspace(0,self.maxvdisp,10)
827
-
828
843
  im1=ax1.contourf(self.xc,self.yc,mom2.T,levels=mom2levs,cmap=sauron,vmax=self.maxvdisp)
829
844
 
830
845
  if self.all_axes_physical:
@@ -844,7 +859,7 @@ class pymakeplots:
844
859
  vticks=np.arange(0,5)*dvticks
845
860
 
846
861
  cb=self.colorbar(im1,ticks=vticks)
847
- cb.set_label("$\sigma_{obs}$ (km s$^{-1}$)")
862
+ cb.set_label('$\\sigma_{obs}$ (km s$^{-1}$)')
848
863
 
849
864
 
850
865
  self.add_beam(ax1)
@@ -955,10 +970,10 @@ class pymakeplots:
955
970
 
956
971
  def make_pvd(self,axes=None,fits=False,pdf=False):
957
972
  self.fits=fits
958
- if np.any(self.xc) == None:
973
+ if np.any(self.xc == None):
959
974
  self.prepare_cubes()
960
975
 
961
- if np.any(axes) == None:
976
+ if np.any(axes == None):
962
977
  self.set_rc_params(mult=0.75)
963
978
  fig,axes=plt.subplots(1,figsize=(7,5))
964
979
  outsideaxis=0
@@ -969,32 +984,67 @@ class pymakeplots:
969
984
  if self.posang==None:
970
985
  # try fitting the moment one to get the kinematic pa
971
986
  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)
987
+ mom0=(self.flat_cube_trim*self.mask_trim).sum(axis=2)
973
988
  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
989
+ mom1[mom0 != 0.0] = (((self.flat_cube_trim*self.mask_trim)*self.vcoord_trim).sum(axis=2))[mom0 != 0.0]/mom0[mom0 != 0.0]
990
+ mom1=mom1.T
976
991
 
977
-
992
+ # ### sigma clip
993
+ # mom1[np.abs(mom1/np.nanstd(mom1))>5]=np.nan
994
+
995
+ ### select largest contigious structure
996
+ label,cnt=ndimage.label(self.mask_trim.sum(axis=2))
997
+ mode_label= mode(label[label>0])
998
+
999
+ hist,lab=np.histogram(label[label>0],bins=np.arange(cnt+1)+1)
1000
+ beampix=(self.bmaj*self.bmin)/(self.cellsize**2)
1001
+
1002
+
1003
+ if len(lab[0:-1][hist<beampix]) != len(lab[0:-1]):
1004
+
1005
+ ## remove beam size artifacts
1006
+ for thelabel in lab[0:-1][hist<beampix]:
1007
+ mom1[label.T == thelabel]=np.nan
1008
+
1009
+ ## keep biggest structures that contain >80% of remaining pixels
1010
+ remainlab=lab[0:-1][hist>beampix]
1011
+ remainhist=hist[hist>beampix]
1012
+ st=np.argsort(remainhist)
1013
+ for thelabel in remainlab[st][np.nancumsum(remainhist[st]/np.sum(remainhist)) < 0.2]:
1014
+ mom1[label.T == thelabel]=np.nan
1015
+
1016
+ else:
1017
+ mom1[label.T != mode_label.mode]=np.nan
1018
+
1019
+ #self.useallpixels=True
1020
+
1021
+ ### remove median
1022
+ mom1-=np.nanmedian(mom1)
1023
+
1024
+
1025
+
1026
+ #breakpoint()
978
1027
  # 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)
1028
+ # if (self.pbcorr_cube_trim[:,:,0].size < 50*50) or (self.useallpixels):
1029
+ xv, yv = np.meshgrid(self.xc,self.yc)
1030
+ x,y,v = xv[np.isfinite(mom1)],yv[np.isfinite(mom1)],mom1[np.isfinite(mom1)]
1031
+ # else:
1032
+ # print("Downsampling the observed moment one in PA estimate for speed. Set `useallpixels` to override.")
1033
+ #mom1[np.isfinite(mom1) == False] = self.vsys
1034
+ #breakpoint()
1035
+ # interper = interpolate.RegularGridInterpolator((self.xc,self.yc),(mom1-self.vsys).T,bounds_error=False,fill_value=np.nan)
1036
+ # x=np.linspace(np.min(self.xc),np.max(self.xc),self.xc.size//2)
1037
+ # y=np.linspace(np.min(self.yc),np.max(self.yc),self.yc.size//2)
1038
+ # xv, yv = np.meshgrid(x,y)
1039
+ # v= interper((xv,yv))
1040
+ # x,y,v = xv.flatten(),yv.flatten(),v.flatten()
994
1041
 
1042
+ #breakpoint()
1043
+ self.posang,_,_ = fit_kinematic_pa(x[np.isfinite(v)],y[np.isfinite(v)],v[np.isfinite(v)],nsteps=36,plot=False,quiet=True)
1044
+
995
1045
  if np.sin(np.deg2rad((self.posang+45)*2)) > 0:
996
1046
  # do y axis cut
997
- if np.nanmean(mom1[self.yc > 0,:]) > np.nanmean(mom1[self.yc < 0,:]):
1047
+ if np.nansum(mom1[self.yc > 0,:])/(mom1[self.yc > 0,:]).size > np.nansum(mom1[self.yc < 0,:])/(mom1[self.yc < 0,:]).size:
998
1048
  # posang should be gt 180
999
1049
  if self.posang < 180: self.posang += 180
1000
1050
  else:
@@ -1002,15 +1052,14 @@ class pymakeplots:
1002
1052
  if self.posang > 180: self.posang -= 180
1003
1053
  else:
1004
1054
  # do x axis cut
1005
- if np.nanmean(mom1[:,self.xc > 0]) > np.nanmean(mom1[:,self.xc < 0]):
1055
+ if np.nansum(mom1[:,self.xc > 0])/(mom1[:,self.xc > 0]).size > np.nansum(mom1[:,self.xc < 0])/(mom1[:,self.xc < 0]).size:
1006
1056
  # posang should be gt 180
1007
1057
  if self.posang < 180: self.posang += 180
1008
1058
  else:
1009
1059
  # posang should be lt 180
1010
1060
  if self.posang > 180: self.posang -= 180
1011
1061
  if not self.silent: print("PA estimate (degrees): ",np.round(self.posang,1))
1012
-
1013
-
1062
+
1014
1063
  centpix_x=np.where(np.isclose(self.xc,0.0,atol=self.cellsize/1.9))[0]
1015
1064
  centpix_y=np.where(np.isclose(self.yc,0.0,atol=self.cellsize/1.9))[0]
1016
1065
 
@@ -1047,9 +1096,15 @@ class pymakeplots:
1047
1096
  newcmp = ListedColormap(oldcmp(np.linspace(0.15, 1, 256)))
1048
1097
 
1049
1098
 
1099
+ if np.nanmax(pvd) < self.cliplevel:
1100
+ contour_levels=np.linspace(np.nanmax(pvd)/2.,np.nanmax(pvd),10)
1101
+ if np.sum(contour_levels)==0:
1102
+ contour_levels=np.array([self.cliplevel,self.cliplevel+0.1])
1103
+ else:
1104
+ contour_levels=np.linspace(self.cliplevel,np.nanmax(pvd),10)
1050
1105
 
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')
1106
+ axes.contourf(pvdaxis,vaxis,pvd.T,levels=contour_levels,cmap=newcmp)
1107
+ axes.contour(pvdaxis,vaxis,pvd.T,levels=contour_levels,colors='black')
1053
1108
 
1054
1109
  if self.all_axes_physical:
1055
1110
  axes.set_xlabel('Offset (kpc)')
@@ -1067,7 +1122,7 @@ class pymakeplots:
1067
1122
  secax = axes.secondary_yaxis('right', functions=(self.vsystrans, self.vsystrans_inv))
1068
1123
  secax.set_ylabel(r'V$_{\rm offset}$ (km s$^{-1}$)')
1069
1124
 
1070
- anchored_text = AnchoredText("PA: "+str(round(self.posang,1))+"$^{\circ}$", loc=loc1,frameon=False)
1125
+ anchored_text = AnchoredText("PA: "+str(round(self.posang,1))+'$^{\\circ}$', loc=loc1,frameon=False)
1071
1126
  axes.add_artist(anchored_text)
1072
1127
 
1073
1128
  if self.gal_distance != None and not self.all_axes_physical:
@@ -1078,24 +1133,31 @@ class pymakeplots:
1078
1133
 
1079
1134
  if pdf:
1080
1135
  plt.savefig(self.galname+"_pvd.pdf", bbox_inches = 'tight')
1136
+ plt.close()
1081
1137
  else:
1082
1138
  if not outsideaxis: plt.show()
1083
1139
 
1084
1140
  def make_spec(self,axes=None,fits=False,pdf=False,onlydata=False,nsum=False,highlight=False):
1085
1141
  self.fits=fits
1086
- if np.any(self.xc) == None:
1142
+ if np.any(self.xc == None):
1087
1143
  self.prepare_cubes()
1088
1144
 
1089
- if axes == None:
1145
+ if np.any(axes == None):
1090
1146
  self.set_rc_params(mult=0.75)
1091
1147
  fig,axes=plt.subplots(1,figsize=(7,5))
1092
1148
  outsideaxis=0
1093
1149
  else:
1094
1150
  outsideaxis=1
1095
- spec=self.pbcorr_cube[self.spatial_trim[0]:self.spatial_trim[1],self.spatial_trim[2]:self.spatial_trim[3],:].sum(axis=0).sum(axis=0)
1151
+ #spec=self.pbcorr_cube[self.spatial_trim[0]:self.spatial_trim[1],self.spatial_trim[2]:self.spatial_trim[3],:].sum(axis=0).sum(axis=0)
1152
+
1153
+ mask2d=self.mask_trim.sum(axis=2).reshape((self.mask_trim.shape[0],self.mask_trim.shape[1],1)).astype(bool)
1154
+ mask2d=ndimage.binary_dilation(mask2d,iterations=2)
1155
+ spec=(self.pbcorr_cube[self.spatial_trim[0]:self.spatial_trim[1],self.spatial_trim[2]:self.spatial_trim[3],:]*mask2d).sum(axis=0).sum(axis=0)
1156
+
1157
+
1096
1158
  spec_mask=(self.pbcorr_cube_trim*self.mask_trim).sum(axis=0).sum(axis=0)
1097
1159
  ylab="Unknown"
1098
- #breakpoint()
1160
+
1099
1161
  if (''.join(self.bunit.split())).lower() == "Jy/beam".lower():
1100
1162
 
1101
1163
  spec*=1/self.beam_area()
@@ -1149,6 +1211,7 @@ class pymakeplots:
1149
1211
 
1150
1212
  if pdf:
1151
1213
  plt.savefig(self.galname+"_spec.pdf", bbox_inches = 'tight')
1214
+ plt.close()
1152
1215
  else:
1153
1216
  if not outsideaxis: plt.show()
1154
1217
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymakeplots
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Home-page: https://github.com/TimothyADavis/pymakeplots
5
5
  Author: Timothy A. Davis
6
6
  Author-email: DavisT@cardiff.ac.uk
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
 
7
7
  setup(name='pymakeplots',
8
- version='0.2.1',
8
+ version='0.2.3',
9
9
  description='',
10
10
  url='https://github.com/TimothyADavis/pymakeplots',
11
11
  author='Timothy A. Davis',
File without changes
File without changes
File without changes