Repository: RadioAstronomySoftwareGroup/pyuvdata

Issue:
add E/N pol strings if x_polarization is set

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580?src=pr&el=h1) Report
> Merging [#580](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580?src=pr&el=desc) into [master](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/commit/dce3dca1b79bd07d136af9465c7cc815f669c016?src=pr&el=desc) will **decrease** coverage by `0.23%`.
> The diff coverage is `82.56%`.

[![Impacted file tree graph](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580/graphs/tree.svg?width=650&token=4QykcCeB1H&height=150&src=pr)](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #580      +/-   ##
==========================================
- Coverage   98.81%   98.58%   -0.24%     
==========================================
  Files          20       20              
  Lines        7755     7830      +75     
==========================================
+ Hits         7663     7719      +56     
- Misses         92      111      +19
```


| [Impacted Files](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pyuvdata/utils.py](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580/diff?src=pr&el=tree#diff-cHl1dmRhdGEvdXRpbHMucHk=) | `100% <100%> (ø)` | :arrow_up: |
| [pyuvdata/uvbeam.py](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580/diff?src=pr&el=tree#diff-cHl1dmRhdGEvdXZiZWFtLnB5) | `99.27% <100%> (ø)` | :arrow_up: |
| [pyuvdata/cst\_beam.py](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580/diff?src=pr&el=tree#diff-cHl1dmRhdGEvY3N0X2JlYW0ucHk=) | `100% <100%> (ø)` | :arrow_up: |
| [pyuvdata/miriad.py](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580/diff?src=pr&el=tree#diff-cHl1dmRhdGEvbWlyaWFkLnB5) | `97.26% <100%> (ø)` | :arrow_up: |
| [pyuvdata/uvcal.py](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580/diff?src=pr&el=tree#diff-cHl1dmRhdGEvdXZjYWwucHk=) | `98.41% <18.18%> (-1.59%)` | :arrow_down: |
| [pyuvdata/uvdata.py](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580/diff?src=pr&el=tree#diff-cHl1dmRhdGEvdXZkYXRhLnB5) | `99.37% <55%> (-0.63%)` | :arrow_down: |
| [pyuvdata/beamfits.py](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580/diff?src=pr&el=tree#diff-cHl1dmRhdGEvYmVhbWZpdHMucHk=) | `99.74% <66.66%> (-0.26%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580?src=pr&el=footer). Last update [dce3dca...5378326](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/pull/580?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 7d5f0d2b..909b8891 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -54,7 +54,7 @@ jobs:
           command: |
             source activate ${ENV_NAME}
             mkdir test-reports
-            nosetests pyuvdata -v --with-xunit --xunit-file=test-reports/xunit.xml --with-coverage --cover-package=pyuvdata --cover-xml
+            nosetests pyuvdata --with-xunit --xunit-file=test-reports/xunit.xml --with-coverage --cover-package=pyuvdata --cover-xml
       - save_cache:
           key: deps-{{ .Branch }}-{{ checksum "ci/pyuvdata_tests.yml" }}
           paths:
@@ -92,7 +92,7 @@ jobs:
           command: |
             source activate ${ENV_NAME}
             mkdir test-reports
-            nosetests pyuvdata -v --with-xunit --xunit-file=test-reports/xunit.xml --with-coverage --cover-package=pyuvdata --cover-xml
+            nosetests pyuvdata --with-xunit --xunit-file=test-reports/xunit.xml --with-coverage --cover-package=pyuvdata --cover-xml
       - save_cache:
           key: deps-{{ .Branch }}-{{ checksum "ci/pyuvdata_min_deps_tests.yml" }}
           paths:
diff --git a/.travis.yml b/.travis.yml
index 267d33bb..94fd1abd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -46,7 +46,7 @@ install:
   - conda info -a
 
   # install dependencies
-  - conda install numpy scipy astropy nose pip h5py six healpy python-casacore pyyaml pycodestyle coveralls python="$PYTHON_VERSION"
+  - conda install numpy scipy astropy nose pip h5py six healpy python-casacore pyyaml pycodestyle coverage python="$PYTHON_VERSION"
   - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
       conda install gcc_linux-64 gxx_linux-64;
     fi
@@ -60,8 +60,3 @@ install:
 script:
   - python setup.py build_ext --force --inplace
   - nosetests pyuvdata --with-coverage --cover-package=pyuvdata
-
-after_success:
-    - coveralls
-notifications:
-  webhooks: https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 759d0274..01277089 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,10 +4,15 @@ All notable changes to this project will be documented in this file.
 ## [Unreleased]
 
 ### Added
+- Optional `x_orientation` parameter to utils functions polstr2num, polnum2str, jstr2num and jnum2str to allow for E/N based polarization strings (rather than just x/y based ones)
+- New optional `x_orientation` parameter on UVBeam (paralleling UVData and UVCal), with read/write support in beamfits
+- Added `x_orientation` as an optional parameter in read_cst_beam and in cst settings yaml files.
+- All str2num or num2str calls on UVData and UVBeam pass the object's x_orientation
 - New `UVData.fast_concat` method to allow fast concatenation of UVData objects (or files) along a particular axis.
 - Added preliminary `UVFlag` module from hera_qm to pyuvdata. Will eventually promote to `UVBase` object, but for now this is undocumented functionality.
 
 ### Deprecated
+- Defined 'east' and 'north' as the allowed 'x_orientation' values in UVData and UVCal, Backwards compatiblity support exists for 'E' and 'N' values
 - `UVData.order_pols` method in favor of `UVData.reorder_pols`.
 
 ### Fixed
diff --git a/README.md b/README.md
index 7bfcfbd0..e0992507 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
 
 [![Build Status](https://travis-ci.org/RadioAstronomySoftwareGroup/pyuvdata.svg?branch=master)](https://travis-ci.org/RadioAstronomySoftwareGroup/pyuvdata)
 [![CircleCI](https://circleci.com/gh/RadioAstronomySoftwareGroup/pyuvdata.svg?style=svg&branch=master)](https://circleci.com/gh/RadioAstronomySoftwareGroup/pyuvdata?branch=master)
-[![Coverage Status](https://coveralls.io/repos/github/RadioAstronomySoftwareGroup/pyuvdata/badge.svg?branch=master)](https://coveralls.io/github/RadioAstronomySoftwareGroup/pyuvdata?branch=master)
 [![codecov](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/badge.svg?branch=master)](https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata)
 
 pyuvdata defines a pythonic interface to interferometric data sets. Currently pyuvdata supports reading and writing of miriad, uvfits, and uvh5 files and reading of CASA measurement sets and FHD ([Fast Holographic Deconvolution](https://github.com/EoRImaging/FHD)) visibility save files.
diff --git a/docs/make_index.py b/docs/make_index.py
index 0c18c989..bf3ac96b 100644
--- a/docs/make_index.py
+++ b/docs/make_index.py
@@ -33,8 +33,6 @@ def write_index_rst(readme_file=None, write_file=None):
         '    :target: https://travis-ci.org/RadioAstronomySoftwareGroup/pyuvdata\n\n'
         '.. image:: https://circleci.com/gh/RadioAstronomySoftwareGroup/pyuvdata.svg?style=svg\n'
         '    :target: https://circleci.com/gh/RadioAstronomySoftwareGroup/pyuvdata\n\n'
-        '.. image:: https://coveralls.io/repos/github/RadioAstronomySoftwareGroup/pyuvdata/badge.svg\n'
-        '    :target: https://coveralls.io/github/RadioAstronomySoftwareGroup/pyuvdata\n\n'
         '.. image:: https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata/branch/master/graph/badge.svg\n'
         '  :target: https://codecov.io/gh/RadioAstronomySoftwareGroup/pyuvdata\n\n')
 
diff --git a/pyuvdata/beamfits.py b/pyuvdata/beamfits.py
index cfe1892b..f64337a1 100644
--- a/pyuvdata/beamfits.py
+++ b/pyuvdata/beamfits.py
@@ -168,6 +168,7 @@ class BeamFITS(UVBeam):
             self.feed_version = primary_header.pop('FEEDVER', None)
             self.model_name = primary_header.pop('MODEL', None)
             self.model_version = primary_header.pop('MODELVER', None)
+            self.x_orientation = primary_header.pop('XORIENT', None)
             self.interpolation_function = primary_header.pop('INTERPFN', None)
             self.freq_interp_kind = primary_header.pop('FINTERP', None)
 
@@ -408,6 +409,9 @@ class BeamFITS(UVBeam):
         primary_header['MODEL'] = self.model_name
         primary_header['MODELVER'] = self.model_version
 
+        if self.x_orientation is not None:
+            primary_header['XORIENT'] = self.x_orientation
+
         if self.interpolation_function is not None:
             primary_header['INTERPFN'] = (self.interpolation_function,
                                           'interpolation function')
diff --git a/pyuvdata/cst_beam.py b/pyuvdata/cst_beam.py
index 691f50ae..f2901f6a 100644
--- a/pyuvdata/cst_beam.py
+++ b/pyuvdata/cst_beam.py
@@ -45,8 +45,9 @@ class CSTBeam(UVBeam):
 
     def read_cst_beam(self, filename, beam_type='power', feed_pol='x',
                       rotate_pol=True, frequency=None, telescope_name=None,
-                      feed_name=None, feed_version=None, model_name=None, model_version=None,
-                      history='', reference_impedance=None, extra_keywords=None,
+                      feed_name=None, feed_version=None, model_name=None,
+                      model_version=None, history='', x_orientation=None,
+                      reference_impedance=None, extra_keywords=None,
                       run_check=True, check_extra=True, run_check_acceptability=True):
 
         """
@@ -68,6 +69,9 @@ class CSTBeam(UVBeam):
             model_name: the name of the model corresponding to the filename.
             model_version: the version of the model corresponding to the filename.
             history: A string detailing the history of the filename.
+            x_orientation: Orientation of the physical dipole corresponding to what is
+                labelled as the x polarization. Options are "east" (indicating
+                east/west orientation) and "north" (indicating north/south orientation)
             reference_impedance (float): The reference impedance of the model(s).
             extra_keywords (dict): a dictionary containing any extra_keywords.
             run_check: Option to check for the existence and proper shapes of
@@ -86,6 +90,8 @@ class CSTBeam(UVBeam):
         if not uvutils._check_history_version(self.history, self.pyuvdata_version_str):
             self.history += self.pyuvdata_version_str
 
+        if x_orientation is not None:
+            self.x_orientation = x_orientation
         if reference_impedance is not None:
             self.reference_impedance = float(reference_impedance)
         if extra_keywords is not None:
diff --git a/pyuvdata/data/NicCSTbeams/HERA_Vivaldi_CST_beams.yaml b/pyuvdata/data/NicCSTbeams/HERA_Vivaldi_CST_beams.yaml
index 45d861ed..50fe38f9 100644
--- a/pyuvdata/data/NicCSTbeams/HERA_Vivaldi_CST_beams.yaml
+++ b/pyuvdata/data/NicCSTbeams/HERA_Vivaldi_CST_beams.yaml
@@ -10,6 +10,7 @@ frequencies: [50e6, 51e6, 52e6, 53e6, 54e6, 55e6, 56e6, 57e6, 58e6, 59e6, 60e6,
 filenames: ['farfield (f=50) [1].txt', 'farfield (f=51) [1].txt', 'farfield (f=52) [1].txt', 'farfield (f=53) [1].txt', 'farfield (f=54) [1].txt', 'farfield (f=55) [1].txt', 'farfield (f=56) [1].txt', 'farfield (f=57) [1].txt', 'farfield (f=58) [1].txt', 'farfield (f=59) [1].txt', 'farfield (f=60) [1].txt', 'farfield (f=61) [1].txt', 'farfield (f=62) [1].txt', 'farfield (f=63) [1].txt', 'farfield (f=64) [1].txt', 'farfield (f=65) [1].txt', 'farfield (f=66) [1].txt', 'farfield (f=67) [1].txt', 'farfield (f=68) [1].txt', 'farfield (f=69) [1].txt', 'farfield (f=70) [1].txt', 'farfield (f=71) [1].txt', 'farfield (f=72) [1].txt', 'farfield (f=73) [1].txt', 'farfield (f=74) [1].txt', 'farfield (f=75) [1].txt', 'farfield (f=76) [1].txt', 'farfield (f=77) [1].txt', 'farfield (f=78) [1].txt', 'farfield (f=79) [1].txt', 'farfield (f=80) [1].txt', 'farfield (f=81) [1].txt', 'farfield (f=82) [1].txt', 'farfield (f=83) [1].txt', 'farfield (f=84) [1].txt', 'farfield (f=85) [1].txt', 'farfield (f=86) [1].txt', 'farfield (f=87) [1].txt', 'farfield (f=88) [1].txt', 'farfield (f=89) [1].txt', 'farfield (f=90) [1].txt', 'farfield (f=91) [1].txt', 'farfield (f=92) [1].txt', 'farfield (f=93) [1].txt', 'farfield (f=94) [1].txt', 'farfield (f=95) [1].txt', 'farfield (f=96) [1].txt', 'farfield (f=97) [1].txt', 'farfield (f=98) [1].txt', 'farfield (f=99) [1].txt', 'farfield (f=100) [1].txt', 'farfield (f=101) [1].txt', 'farfield (f=102) [1].txt', 'farfield (f=103) [1].txt', 'farfield (f=104) [1].txt', 'farfield (f=105) [1].txt', 'farfield (f=106) [1].txt', 'farfield (f=107) [1].txt', 'farfield (f=108) [1].txt', 'farfield (f=109) [1].txt', 'farfield (f=110) [1].txt', 'farfield (f=111) [1].txt', 'farfield (f=112) [1].txt', 'farfield (f=113) [1].txt', 'farfield (f=114) [1].txt', 'farfield (f=115) [1].txt', 'farfield (f=116) [1].txt', 'farfield (f=117) [1].txt', 'farfield (f=118) [1].txt', 'farfield (f=119) [1].txt', 'farfield (f=120) [1].txt', 'farfield (f=121) [1].txt', 'farfield (f=122) [1].txt', 'farfield (f=123) [1].txt', 'farfield (f=124) [1].txt', 'farfield (f=125) [1].txt', 'farfield (f=126) [1].txt', 'farfield (f=127) [1].txt', 'farfield (f=128) [1].txt', 'farfield (f=129) [1].txt', 'farfield (f=130) [1].txt', 'farfield (f=131) [1].txt', 'farfield (f=132) [1].txt', 'farfield (f=133) [1].txt', 'farfield (f=134) [1].txt', 'farfield (f=135) [1].txt', 'farfield (f=136) [1].txt', 'farfield (f=137) [1].txt', 'farfield (f=138) [1].txt', 'farfield (f=139) [1].txt', 'farfield (f=140) [1].txt', 'farfield (f=141) [1].txt', 'farfield (f=142) [1].txt', 'farfield (f=143) [1].txt', 'farfield (f=144) [1].txt', 'farfield (f=145) [1].txt', 'farfield (f=146) [1].txt', 'farfield (f=147) [1].txt', 'farfield (f=148) [1].txt', 'farfield (f=149) [1].txt', 'farfield (f=150) [1].txt', 'farfield (f=151) [1].txt', 'farfield (f=152) [1].txt', 'farfield (f=153) [1].txt', 'farfield (f=154) [1].txt', 'farfield (f=155) [1].txt', 'farfield (f=156) [1].txt', 'farfield (f=157) [1].txt', 'farfield (f=158) [1].txt', 'farfield (f=159) [1].txt', 'farfield (f=160) [1].txt', 'farfield (f=161) [1].txt', 'farfield (f=162) [1].txt', 'farfield (f=163) [1].txt', 'farfield (f=164) [1].txt', 'farfield (f=165) [1].txt', 'farfield (f=166) [1].txt', 'farfield (f=167) [1].txt', 'farfield (f=168) [1].txt', 'farfield (f=169) [1].txt', 'farfield (f=170) [1].txt', 'farfield (f=171) [1].txt', 'farfield (f=172) [1].txt', 'farfield (f=173) [1].txt', 'farfield (f=174) [1].txt', 'farfield (f=175) [1].txt', 'farfield (f=176) [1].txt', 'farfield (f=177) [1].txt', 'farfield (f=178) [1].txt', 'farfield (f=179) [1].txt', 'farfield (f=180) [1].txt', 'farfield (f=181) [1].txt', 'farfield (f=182) [1].txt', 'farfield (f=183) [1].txt', 'farfield (f=184) [1].txt', 'farfield (f=185) [1].txt', 'farfield (f=186) [1].txt', 'farfield (f=187) [1].txt', 'farfield (f=188) [1].txt', 'farfield (f=189) [1].txt', 'farfield (f=190) [1].txt', 'farfield (f=191) [1].txt', 'farfield (f=192) [1].txt', 'farfield (f=193) [1].txt', 'farfield (f=194) [1].txt', 'farfield (f=195) [1].txt', 'farfield (f=196) [1].txt', 'farfield (f=197) [1].txt', 'farfield (f=198) [1].txt', 'farfield (f=199) [1].txt', 'farfield (f=200) [1].txt', 'farfield (f=201) [1].txt', 'farfield (f=202) [1].txt', 'farfield (f=203) [1].txt', 'farfield (f=204) [1].txt', 'farfield (f=205) [1].txt', 'farfield (f=206) [1].txt', 'farfield (f=207) [1].txt', 'farfield (f=208) [1].txt', 'farfield (f=209) [1].txt', 'farfield (f=210) [1].txt', 'farfield (f=211) [1].txt', 'farfield (f=212) [1].txt', 'farfield (f=213) [1].txt', 'farfield (f=214) [1].txt', 'farfield (f=215) [1].txt', 'farfield (f=216) [1].txt', 'farfield (f=217) [1].txt', 'farfield (f=218) [1].txt', 'farfield (f=219) [1].txt', 'farfield (f=220) [1].txt', 'farfield (f=221) [1].txt', 'farfield (f=222) [1].txt', 'farfield (f=223) [1].txt', 'farfield (f=224) [1].txt', 'farfield (f=225) [1].txt', 'farfield (f=226) [1].txt', 'farfield (f=227) [1].txt', 'farfield (f=228) [1].txt', 'farfield (f=229) [1].txt', 'farfield (f=230) [1].txt', 'farfield (f=231) [1].txt', 'farfield (f=232) [1].txt', 'farfield (f=233) [1].txt', 'farfield (f=234) [1].txt', 'farfield (f=235) [1].txt', 'farfield (f=236) [1].txt', 'farfield (f=237) [1].txt', 'farfield (f=238) [1].txt', 'farfield (f=239) [1].txt', 'farfield (f=240) [1].txt', 'farfield (f=241) [1].txt', 'farfield (f=242) [1].txt', 'farfield (f=243) [1].txt', 'farfield (f=244) [1].txt', 'farfield (f=245) [1].txt', 'farfield (f=246) [1].txt', 'farfield (f=247) [1].txt', 'farfield (f=248) [1].txt', 'farfield (f=249) [1].txt', 'farfield (f=250) [1].txt']
 sim_beam_type: E-farfield
 feed_pol: x
+x_orientation: east
 layout: 1 antenna
 port_num: 1
 ref_imp: 100
diff --git a/pyuvdata/data/NicCSTbeams/NicCSTbeams.yaml b/pyuvdata/data/NicCSTbeams/NicCSTbeams.yaml
index e303da93..5aff9181 100644
--- a/pyuvdata/data/NicCSTbeams/NicCSTbeams.yaml
+++ b/pyuvdata/data/NicCSTbeams/NicCSTbeams.yaml
@@ -12,6 +12,7 @@ filenames: ['HERA_NicCST_150MHz.txt', 'HERA_NicCST_123MHz.txt']
 # feed_pol specifies which feed polarization is simulated in these files.
 # Can be a list of the same length as filenames
 feed_pol: x
+x_orientation: east
 sim_beam_type: E-farfield
 layout: 1 antenna
 port_num: 1
diff --git a/pyuvdata/miriad.py b/pyuvdata/miriad.py
index bf9fb0db..df37ef48 100644
--- a/pyuvdata/miriad.py
+++ b/pyuvdata/miriad.py
@@ -187,9 +187,12 @@ class Miriad(UVData):
             # type check
             err_msg = "pols must be a list of polarization strings or ints, Ex: ['xx', ...] or [-5, ...]"
             assert isinstance(polarizations, (list, np.ndarray)), err_msg
-            assert np.array(map(lambda p: isinstance(p, (str, np.str, int, np.integer)), polarizations)).all(), err_msg
+            assert np.array(map(lambda p: isinstance(p, (str, np.str, int, np.integer)),
+                                polarizations)).all(), err_msg
             # convert to pol integer if string
-            polarizations = [p if isinstance(p, (int, np.integer)) else uvutils.polstr2num(p) for p in polarizations]
+            polarizations = [p if isinstance(p, (int, np.integer))
+                             else uvutils.polstr2num(p, x_orientation=self.x_orientation)
+                             for p in polarizations]
             # iterate through all possible pols and reject if not in pols
             pol_list = []
             for p in np.arange(-8, 5):
diff --git a/pyuvdata/utils.py b/pyuvdata/utils.py
index db0191e0..a6d7e0a1 100644
--- a/pyuvdata/utils.py
+++ b/pyuvdata/utils.py
@@ -495,59 +495,158 @@ def _fits_indexhdus(hdulist):
     return tablenames
 
 
-def polstr2num(pol):
+def _x_orientation_rep_dict(x_orientation):
+    """"Helper function to create replacement dict based on x_orientation"""
+    if x_orientation.lower() == 'east' or x_orientation.lower() == 'e':
+        return {'x': 'e', 'y': 'n'}
+    elif x_orientation.lower() == 'north' or x_orientation.lower() == 'n':
+        return {'x': 'n', 'y': 'e'}
+    else:
+        raise ValueError('x_orientation not recognized.')
+
+
+def polstr2num(pol, x_orientation=None):
     """
     Convert polarization str to number according to AIPS Memo 117.
+
     Prefer 'pI', 'pQ', 'pU' and 'pV' to make it clear that these are pseudo-Stokes,
-    not true Stokes, but also support 'I', 'Q', 'U', 'V'.
+    not true Stokes, but also supports 'I', 'Q', 'U', 'V'.
+
+    Parameters
+    ----------
+    pol : str
+        polarization string
+    x_orientation : str, optional
+        Orientation of the physical dipole corresponding to what is
+        labelled as the x polarization ("east" or "north") to allow for
+        converting from E/N strings. See corresonding parameter on UVData
+        for more details.
+
+    Returns
+    ----------
+    int
+        Number corresponding to string
 
-    Args:
-        pol: polarization string
+    Raises
+    ------
+    ValueError
+        If the pol string cannot be converted to a polarization number.
 
-    Returns:
-        Number corresponding to string
+    Warns
+    ------
+    UserWarning
+        If the x_orientation not recognized.
     """
-    poldict = {k.lower(): v for k, v in six.iteritems(POL_STR2NUM_DICT)}
+    dict_use = copy.deepcopy(POL_STR2NUM_DICT)
+    if x_orientation is not None:
+        try:
+            rep_dict = _x_orientation_rep_dict(x_orientation)
+            for key, value in six.iteritems(POL_STR2NUM_DICT):
+                new_key = key.replace('x', rep_dict['x']).replace('y', rep_dict['y'])
+                dict_use[new_key] = value
+        except ValueError:
+            warnings.warn('x_orientation not recognized.')
+
+    poldict = {k.lower(): v for k, v in six.iteritems(dict_use)}
     if isinstance(pol, str):
         out = poldict[pol.lower()]
     elif isinstance(pol, collections.Iterable):
         out = [poldict[key.lower()] for key in pol]
     else:
-        raise ValueError('Polarization {p} cannot be converted to index.'.format(p=pol))
+        raise ValueError('Polarization {p} cannot be converted to a polarization number.'.format(p=pol))
     return out
 
 
-def polnum2str(num):
+def polnum2str(num, x_orientation=None):
     """
     Convert polarization number to str according to AIPS Memo 117.
-    Use 'pI', 'pQ', 'pU' and 'pV' to make it clear that these are pseudo-Stokes, not true Stokes
 
-    Args:
-        num: polarization number
-
-    Returns:
-        String corresponding to string
+    Uses 'pI', 'pQ', 'pU' and 'pV' to make it clear that these are pseudo-Stokes,
+    not true Stokes
+
+    Parameters
+    ----------
+    num : int
+        polarization number
+    x_orientation : str, optional
+        Orientation of the physical dipole corresponding to what is
+        labelled as the x polarization ("east" or "north") to convert to
+        E/N strings. See corresonding parameter on UVData for more details.
+
+    Returns
+    ----------
+    str
+        String corresponding to polarization number
+
+    Raises
+    ------
+    ValueError
+        If the polarization number cannot be converted to a polarization string.
+
+    Warns
+    ------
+    UserWarning
+        If the x_orientation not recognized.
     """
+    dict_use = copy.deepcopy(POL_NUM2STR_DICT)
+    if x_orientation is not None:
+        try:
+            rep_dict = _x_orientation_rep_dict(x_orientation)
+            for key, value in six.iteritems(POL_NUM2STR_DICT):
+                new_val = value.replace('x', rep_dict['x']).replace('y', rep_dict['y'])
+                dict_use[key] = new_val
+        except ValueError:
+            warnings.warn('x_orientation not recognized.')
+
     if isinstance(num, six.integer_types + (np.int32, np.int64)):
-        out = POL_NUM2STR_DICT[num]
+        out = dict_use[num]
     elif isinstance(num, collections.Iterable):
-        out = [POL_NUM2STR_DICT[i] for i in num]
+        out = [dict_use[i] for i in num]
     else:
         raise ValueError('Polarization {p} cannot be converted to string.'.format(p=num))
     return out
 
 
-def jstr2num(jstr):
+def jstr2num(jstr, x_orientation=None):
     """
     Convert jones polarization str to number according to calfits memo.
 
-    Args:
-        jones: antenna polarization string
-
-    Returns:
-        Number corresponding to string
+    Parameters
+    ----------
+    jstr : str
+        antenna (jones) polarization string
+    x_orientation : str, optional
+        Orientation of the physical dipole corresponding to what is
+        labelled as the x polarization ("east" or "north") to allow for
+        converting from E/N strings. See corresonding parameter on UVData
+        for more details.
+
+    Returns
+    ----------
+    int
+        antenna (jones) polarization number corresponding to string
+
+    Raises
+    ------
+    ValueError
+        If the jones string cannot be converted to a polarization number.
+
+    Warns
+    ------
+    UserWarning
+        If the x_orientation not recognized.
     """
-    jdict = {k.lower(): v for k, v in six.iteritems(JONES_STR2NUM_DICT)}
+    dict_use = copy.deepcopy(JONES_STR2NUM_DICT)
+    if x_orientation is not None:
+        try:
+            rep_dict = _x_orientation_rep_dict(x_orientation)
+            for key, value in six.iteritems(JONES_STR2NUM_DICT):
+                new_key = key.replace('x', rep_dict['x']).replace('y', rep_dict['y'])
+                dict_use[new_key] = value
+        except ValueError:
+            warnings.warn('x_orientation not recognized.')
+
+    jdict = {k.lower(): v for k, v in six.iteritems(dict_use)}
     if isinstance(jstr, str):
         out = jdict[jstr.lower()]
     elif isinstance(jstr, collections.Iterable):
@@ -557,51 +656,116 @@ def jstr2num(jstr):
     return out
 
 
-def jnum2str(jnum):
+def jnum2str(jnum, x_orientation=None):
     """
     Convert jones polarization number to str according to calfits memo.
 
-    Args:
-        num: polarization number
-
-    Returns:
-        String corresponding to string
+    Parameters
+    ----------
+    num : int
+        antenna (jones) polarization number
+    x_orientation : str, optional
+        Orientation of the physical dipole corresponding to what is
+        labelled as the x polarization ("east" or "north") to convert to
+        E/N strings. See corresonding parameter on UVData for more details.
+
+    Returns
+    ----------
+    str
+        antenna (jones) polarization string corresponding to number
+
+    Raises
+    ------
+    ValueError
+        If the jones polarization number cannot be converted to a jones polarization string.
+
+    Warns
+    ------
+    UserWarning
+        If the x_orientation not recognized.
     """
+    dict_use = copy.deepcopy(JONES_NUM2STR_DICT)
+    if x_orientation is not None:
+        try:
+            rep_dict = _x_orientation_rep_dict(x_orientation)
+            for key, value in six.iteritems(JONES_NUM2STR_DICT):
+                new_val = value.replace('x', rep_dict['x']).replace('y', rep_dict['y'])
+                dict_use[key] = new_val
+        except ValueError:
+            warnings.warn('x_orientation not recognized.')
+
     if isinstance(jnum, six.integer_types + (np.int32, np.int64)):
-        out = JONES_NUM2STR_DICT[jnum]
+        out = dict_use[jnum]
     elif isinstance(jnum, collections.Iterable):
-        out = [JONES_NUM2STR_DICT[i] for i in jnum]
+        out = [dict_use[i] for i in jnum]
     else:
         raise ValueError('Jones polarization {j} cannot be converted to string.'.format(j=jnum))
     return out
 
 
-def parse_polstr(polstr):
+def parse_polstr(polstr, x_orientation=None):
     """
-    Parse a polarization string and return in AIPS Memo 117
-    standard. See utils.POL_STR2NUM_DICT for options.
+    Parse a polarization string and return pyuvdata standard polarization string.
+
+    See utils.POL_STR2NUM_DICT for options.
+
+    Parameters
+    ----------
+    polstr : str
+        polarization string
+    x_orientation : str, optional
+        Orientation of the physical dipole corresponding to what is
+        labelled as the x polarization ("east" or "north") to allow for
+        converting from E/N strings. See corresonding parameter on UVData
+        for more details.
+
+    Returns
+    ----------
+    str
+        AIPS Memo 117 standard string
 
-    Args:
-        polstr: polarization string
+    Raises
+    ------
+    ValueError
+        If the pol string cannot be converted to a polarization number.
 
-    Returns:
-        AIPS Memo 117 standard string
+    Warns
+    ------
+    UserWarning
+        If the x_orientation not recognized.
     """
-    return polnum2str(polstr2num(polstr))
+    return polnum2str(polstr2num(polstr, x_orientation=x_orientation),
+                      x_orientation=x_orientation)
 
 
-def parse_jpolstr(jpolstr):
+def parse_jpolstr(jpolstr, x_orientation=None):
     """
-    Parse a Jones polarization string and return in AIPS Memo 117
-    standard. See utils.JONES_STR2NUM_DICT for options.
+    Parse a Jones polarization string and return pyuvdata standard jones string.
 
-    Args:
-        jpolstr: Jones polarization string
+    See utils.JONES_STR2NUM_DICT for options.
 
-    Returns:
-        AIPS Memo 117 standard string
+    Parameters
+    ----------
+    jpolstr : str
+        Jones polarization string
+
+    Returns
+    ----------
+    str
+        calfits memo standard string
+
+    Raises
+    ------
+    ValueError
+        If the jones string cannot be converted to a polarization number.
+
+    Warns
+    ------
+    UserWarning
+        If the x_orientation not recognized.
     """
-    return jnum2str(jstr2num(jpolstr))
+    return jnum2str(jstr2num(jpolstr, x_orientation=x_orientation),
+                    x_orientation=x_orientation)
 
 
 def conj_pol(pol):
diff --git a/pyuvdata/uvbeam.py b/pyuvdata/uvbeam.py
index 97b997ed..b7202b3b 100644
--- a/pyuvdata/uvbeam.py
+++ b/pyuvdata/uvbeam.py
@@ -161,7 +161,7 @@ class UVBeam(UVBase):
                                                    expected_type=int, form=('Npols',),
                                                    acceptable_vals=list(np.arange(-8, 0)) + list(np.arange(1, 5)))
 
-        desc = 'Array of frequencies, shape (Nspws, Nfreqs), units Hz'
+        desc = 'Array of frequencies, center of the channel, shape (Nspws, Nfreqs), units Hz'
         self._freq_array = uvp.UVParameter('freq_array', description=desc,
                                            form=('Nspws', 'Nfreqs'),
                                            expected_type=np.float,
@@ -290,6 +290,14 @@ class UVBeam(UVBase):
                                                 expected_type=np.complex)
 
         # -------- extra, non-required parameters ----------
+        desc = ('Orientation of the physical dipole corresponding to what is '
+                'labelled as the x polarization. Options are "east" '
+                '(indicating east/west orientation) and "north" (indicating '
+                'north/south orientation)')
+        self._x_orientation = uvp.UVParameter('x_orientation', description=desc,
+                                              required=False, expected_type=str,
+                                              acceptable_vals=['east', 'north'])
+
         desc = ('String indicating interpolation function. Must be set to use '
                 'the interp_* methods. Allowed values are : "'
                 + '", "'.join(list(self.interpolation_function_dict.keys())) + '".')
@@ -589,7 +597,8 @@ class UVBeam(UVBase):
 
         pol_strings = ['pI', 'pQ', 'pU', 'pV']
         power_data = np.zeros((1, 1, len(pol_strings), _sh[-2], _sh[-1]), dtype=np.complex)
-        beam_object.polarization_array = np.array([uvutils.polstr2num(ps.upper()) for ps in pol_strings])
+        beam_object.polarization_array = np.array(
+            [uvutils.polstr2num(ps.upper(), x_orientation=self.x_orientation) for ps in pol_strings])
 
         for fq_i in range(Nfreqs):
             jones = np.zeros((_sh[-1], 2, 2), dtype=np.complex)
@@ -605,7 +614,8 @@ class UVBeam(UVBase):
         if self.pixel_coordinate_system != 'healpix':
             power_data = power_data.reshape(power_data.shape[:-1] + (Naxes2, Naxes1))
         beam_object.data_array = power_data
-        beam_object.polarization_array = np.array([uvutils.polstr2num(ps.upper()) for ps in pol_strings])
+        beam_object.polarization_array = np.array(
+            [uvutils.polstr2num(ps.upper(), x_orientation=self.x_orientation) for ps in pol_strings])
         beam_object.Naxes_vec = 1
         beam_object.set_power()
 
@@ -671,7 +681,8 @@ class UVBeam(UVBase):
         pol_strings = []
         for pair in feed_pol_order:
             pol_strings.append(beam_object.feed_array[pair[0]] + beam_object.feed_array[pair[1]])
-        beam_object.polarization_array = np.array([uvutils.polstr2num(ps.upper()) for ps in pol_strings])
+        beam_object.polarization_array = np.array(
+            [uvutils.polstr2num(ps.upper(), x_orientation=self.x_orientation) for ps in pol_strings])
 
         if not keep_basis_vector:
             beam_object.Naxes_vec = 1
@@ -904,7 +915,7 @@ class UVBeam(UVBase):
                 Npol_feeds = self.Npols
                 pol_inds = np.arange(Npol_feeds)
             else:
-                pols = [uvutils.polstr2num(p) for p in polarizations]
+                pols = [uvutils.polstr2num(p, x_orientation=self.x_orientation) for p in polarizations]
                 pol_inds = []
                 for pol in pols:
                     if pol not in self.polarization_array:
@@ -1016,7 +1027,7 @@ class UVBeam(UVBase):
                 Npol_feeds = self.Npols
                 pol_inds = np.arange(Npol_feeds)
             else:
-                pols = [uvutils.polstr2num(p) for p in polarizations]
+                pols = [uvutils.polstr2num(p, x_orientation=self.x_orientation) for p in polarizations]
                 pol_inds = []
                 for pol in pols:
                     if pol not in self.polarization_array:
@@ -1599,7 +1610,7 @@ class UVBeam(UVBase):
         assert self.pixel_coordinate_system == 'healpix', "pixel_coordinate_system must be healpix"
         # assert type is int, not string
         if isinstance(pol, (str, np.str)):
-            pol = uvutils.polstr2num(pol)
+            pol = uvutils.polstr2num(pol, x_orientation=self.x_orientation)
         pol_array = self.polarization_array
         if pol in pol_array:
             stokes_p_ind = np.where(np.isin(pol_array, pol))[0][0]
@@ -1624,7 +1635,7 @@ class UVBeam(UVBase):
           omega : float, integral of the beam across the sky [steradians]
         """
         if isinstance(pol, (str, np.str)):
-            pol = uvutils.polstr2num(pol)
+            pol = uvutils.polstr2num(pol, x_orientation=self.x_orientation)
         if self.beam_type != 'power':
             raise ValueError('beam_type must be power')
         if self.Naxes_vec > 1:
@@ -1659,7 +1670,7 @@ class UVBeam(UVBase):
           omega : float, integral of the beam^2 across the sky [steradians]
         """
         if isinstance(pol, (str, np.str)):
-            pol = uvutils.polstr2num(pol)
+            pol = uvutils.polstr2num(pol, x_orientation=self.x_orientation)
         if self.beam_type != 'power':
             raise ValueError('beam_type must be power')
         if self.Naxes_vec > 1:
@@ -2022,9 +2033,9 @@ class UVBeam(UVBase):
     def read_cst_beam(self, filename, beam_type='power', feed_pol=None, rotate_pol=None,
                       frequency=None, telescope_name=None, feed_name=None,
                       feed_version=None, model_name=None, model_version=None,
-                      history=None, reference_impedance=None, extra_keywords=None,
-                      frequency_select=None, run_check=True, check_extra=True,
-                      run_check_acceptability=True):
+                      history=None, x_orientation=None, reference_impedance=None,
+                      extra_keywords=None, frequency_select=None, run_check=True,
+                      check_extra=True, run_check_acceptability=True):
         """
         Read in data from a cst file.
 
@@ -2043,6 +2054,7 @@ class UVBeam(UVBase):
                     |  - cst text filenames (list(str)) -- path relative to yaml file location
                     |  - feed_pol (str) or (list(str))
                 and they may include the following optional keywords:
+                    |  - x_orientation (str): Optional but strongly encouraged!
                     |  - ref_imp (float): beam model reference impedance
                     |  - sim_beam_type (str): e.g. 'E-farfield'
                     |  - all other fields will go into the extra_keywords attribute
@@ -2066,6 +2078,9 @@ class UVBeam(UVBase):
             model_name (str): the name of the model corresponding to the filename(s).
             model_version (str): the version of the model corresponding to the filename(s).
             history (str): A string detailing the history of the filename(s).
+            x_orientation (str): Orientation of the physical dipole corresponding to what is
+                labelled as the x polarization. Options are "east" (indicating
+                east/west orientation) and "north" (indicating north/south orientation)
             reference_impedance (float): The reference impedance of the model(s).
             extra_keywords (dict): a dictionary containing any extra_keywords.
             frequency_select (list(float)):
@@ -2102,6 +2117,8 @@ class UVBeam(UVBase):
                                    'history': history}
             if 'ref_imp' in settings_dict:
                 overriding_keywords['reference_impedance'] = reference_impedance
+            if 'x_orientation' in settings_dict:
+                overriding_keywords['x_orientation'] = reference_impedance
             for key, val in six.iteritems(overriding_keywords):
                 if val is not None:
                     warnings.warn('The {key} keyword is set, overriding the '
@@ -2125,13 +2142,15 @@ class UVBeam(UVBase):
                 history = settings_dict['history']
             if reference_impedance is None and 'ref_imp' in settings_dict:
                 reference_impedance = float(settings_dict['ref_imp'])
+            if x_orientation is None and 'x_orientation' in settings_dict:
+                x_orientation = settings_dict['x_orientation']
 
             if extra_keywords is None:
                 extra_keywords = {}
 
             known_keys = ['telescope_name', 'feed_name', 'feed_version',
                           'model_name', 'model_version', 'history', 'frequencies',
-                          'filenames', 'feed_pol', 'ref_imp']
+                          'filenames', 'feed_pol', 'ref_imp', 'x_orientation']
             # One of the standard paramters in the settings yaml file is longer than 8 characters.
             # This causes warnings and straight truncation when writing to beamfits files
             # To avoid these, this defines a standard renaming of that paramter
@@ -2235,6 +2254,7 @@ class UVBeam(UVBase):
                                model_name=model_name,
                                model_version=model_version,
                                history=history,
+                               x_orientation=x_orientation,
                                reference_impedance=reference_impedance,
                                extra_keywords=extra_keywords,
                                run_check=run_check, check_extra=check_extra,
@@ -2263,6 +2283,7 @@ class UVBeam(UVBase):
                                     model_name=model_name,
                                     model_version=model_version,
                                     history=history,
+                                    x_orientation=x_orientation,
                                     reference_impedance=reference_impedance,
                                     extra_keywords=extra_keywords,
                                     run_check=run_check, check_extra=check_extra,
@@ -2286,6 +2307,7 @@ class UVBeam(UVBase):
                                        model_name=model_name,
                                        model_version=model_version,
                                        history=history,
+                                       x_orientation=x_orientation,
                                        reference_impedance=reference_impedance,
                                        extra_keywords=extra_keywords,
                                        run_check=run_check, check_extra=check_extra,
diff --git a/pyuvdata/uvcal.py b/pyuvdata/uvcal.py
index 793c08f3..f4a9d7ff 100644
--- a/pyuvdata/uvcal.py
+++ b/pyuvdata/uvcal.py
@@ -96,7 +96,7 @@ class UVCal(UVBase):
                                           'numbers, shape (Nspws).', form=('Nspws',),
                                           expected_type=int)
 
-        desc = 'Array of frequencies, shape (Nspws, Nfreqs), units Hz.'
+        desc = 'Array of frequencies, center of the channel, shape (Nspws, Nfreqs), units Hz.'
         self._freq_array = uvp.UVParameter('freq_array', description=desc,
                                            form=('Nspws', 'Nfreqs'),
                                            expected_type=np.float,
@@ -161,11 +161,12 @@ class UVCal(UVBase):
                                               expected_type=np.float)
 
         desc = ('Orientation of the physical dipole corresponding to what is '
-                'labelled as the x polarization. Examples include "east" '
+                'labelled as the x polarization. Options are "east" '
                 '(indicating east/west orientation) and "north" (indicating '
                 'north/south orientation)')
         self._x_orientation = uvp.UVParameter('x_orientation', description=desc,
-                                              expected_type=str)
+                                              expected_type=str,
+                                              acceptable_vals=['east', 'north'])
 
         # --- cal_type parameters ---
         desc = ('cal type parameter. Values are delay, gain or unknown.')
@@ -296,6 +297,23 @@ class UVCal(UVBase):
         elif self.cal_style == 'redundant':
             self.set_redundant()
 
+        # check for deprecated x_orientation strings and convert to new values (if possible)
+        if self.x_orientation is not None:
+            if self.x_orientation not in self._x_orientation.acceptable_vals:
+                warn_string = ('x_orientation {xval} is not one of [{vals}], '
+                               .format(xval=self.x_orientation,
+                                       vals=(', ').join(self._x_orientation.acceptable_vals)))
+                if self.x_orientation.lower() == 'e':
+                    self.x_orientation = 'east'
+                    warn_string += 'converting to "east".'
+                elif self.x_orientation.lower() == 'n':
+                    self.x_orientation = 'north'
+                    warn_string += 'converting to "north".'
+                else:
+                    warn_string += 'cannot be converted.'
+
+                warnings.warn(warn_string, PendingDeprecationWarning)
+
         # first run the basic check from UVBase
         super(UVCal, self).check(check_extra=check_extra,
                                  run_check_acceptability=run_check_acceptability)
diff --git a/pyuvdata/uvdata.py b/pyuvdata/uvdata.py
index bda326f4..f5905391 100644
--- a/pyuvdata/uvdata.py
+++ b/pyuvdata/uvdata.py
@@ -145,7 +145,7 @@ class UVData(UVBase):
 
         # this dimensionality of freq_array does not allow for different spws
         # to have different dimensions
-        desc = 'Array of frequencies, shape (Nspws, Nfreqs), units Hz'
+        desc = 'Array of frequencies, center of the channel, shape (Nspws, Nfreqs), units Hz'
         self._freq_array = uvp.UVParameter('freq_array', description=desc,
                                            form=('Nspws', 'Nfreqs'),
                                            expected_type=np.float,
@@ -281,11 +281,12 @@ class UVData(UVBase):
 
         # -------- extra, non-required parameters ----------
         desc = ('Orientation of the physical dipole corresponding to what is '
-                'labelled as the x polarization. Examples include "east" '
+                'labelled as the x polarization. Options are "east" '
                 '(indicating east/west orientation) and "north" (indicating '
                 'north/south orientation)')
         self._x_orientation = uvp.UVParameter('x_orientation', description=desc,
-                                              required=False, expected_type=str)
+                                              required=False, expected_type=str,
+                                              acceptable_vals=['east', 'north'])
 
         desc = ('Any user supplied extra keywords, type=dict. Keys should be '
                 '8 character or less strings if writing to uvfits or miriad files. '
@@ -371,6 +372,23 @@ class UVData(UVBase):
         else:
             self.set_unknown_phase_type()
 
+        # check for deprecated x_orientation strings and convert to new values (if possible)
+        if self.x_orientation is not None:
+            if self.x_orientation not in self._x_orientation.acceptable_vals:
+                warn_string = ('x_orientation {xval} is not one of [{vals}], '
+                               .format(xval=self.x_orientation,
+                                       vals=(', ').join(self._x_orientation.acceptable_vals)))
+                if self.x_orientation.lower() == 'e':
+                    self.x_orientation = 'east'
+                    warn_string += 'converting to "east".'
+                elif self.x_orientation.lower() == 'n':
+                    self.x_orientation = 'north'
+                    warn_string += 'converting to "north".'
+                else:
+                    warn_string += 'cannot be converted.'
+
+                warnings.warn(warn_string, PendingDeprecationWarning)
+
         super(UVData, self).check(check_extra=check_extra,
                                   run_check_acceptability=run_check_acceptability)
 
@@ -1600,7 +1618,7 @@ class UVData(UVBase):
             pol_inds = np.zeros(0, dtype=np.int)
             for p in polarizations:
                 if isinstance(p, str):
-                    p_num = uvutils.polstr2num(p)
+                    p_num = uvutils.polstr2num(p, x_orientation=self.x_orientation)
                 else:
                     p_num = p
                 if p_num in self.polarization_array:
@@ -2841,7 +2859,7 @@ class UVData(UVBase):
         """
         Returns list of pols in string format.
         """
-        return uvutils.polnum2str(self.polarization_array)
+        return uvutils.polnum2str(self.polarization_array, x_orientation=self.x_orientation)
 
     def get_antpairpols(self):
         """
@@ -2935,7 +2953,8 @@ class UVData(UVBase):
         key = uvutils._get_iterable(key)
         if type(key) is str:
             # Single string given, assume it is polarization
-            pol_ind1 = np.where(self.polarization_array == uvutils.polstr2num(key))[0]
+            pol_ind1 = np.where(self.polarization_array
+                                == uvutils.polstr2num(key, x_orientation=self.x_orientation))[0]
             if len(pol_ind1) > 0:
                 blt_ind1 = np.arange(self.Nblts, dtype=np.int64)
                 blt_ind2 = np.array([], dtype=np.int64)
@@ -3016,12 +3035,17 @@ class UVData(UVBase):
             if type(key[2]) is str:
                 # pol is str
                 if len(blt_ind1) > 0:
-                    pol_ind1 = np.where(self.polarization_array == uvutils.polstr2num(key[2]))[0]
+                    pol_ind1 = np.where(
+                        self.polarization_array
+                        == uvutils.polstr2num(key[2],
+                                              x_orientation=self.x_orientation))[0]
                 else:
                     pol_ind1 = np.array([], dtype=np.int64)
                 if len(blt_ind2) > 0:
-                    pol_ind2 = np.where(self.polarization_array
-                                        == uvutils.polstr2num(uvutils.conj_pol(key[2])))[0]
+                    pol_ind2 = np.where(
+                        self.polarization_array
+                        == uvutils.polstr2num(uvutils.conj_pol(key[2]),
+                                              x_orientation=self.x_orientation))[0]
                 else:
                     pol_ind2 = np.array([], dtype=np.int64)
             else:
@@ -3402,8 +3426,11 @@ class UVData(UVBase):
                             if pols is not None:
                                 for pol in pols:
                                     if (pol.lower() in pols_data
-                                            and uvutils.polstr2num(pol) not in polarizations):
-                                        polarizations.append(uvutils.polstr2num(pol))
+                                            and uvutils.polstr2num(pol, x_orientation=self.x_orientation)
+                                            not in polarizations):
+                                        polarizations.append(
+                                            uvutils.polstr2num(pol,
+                                                               x_orientation=self.x_orientation))
                                     elif not (pol.lower() in pols_data
                                               or pol in warned_pols):
                                         warned_pols.append(pol)
@@ -3414,8 +3441,11 @@ class UVData(UVBase):
                                         if (self.Npols == 1
                                                 and [pol.lower()] == pols_data):
                                             ant_pairs_nums.remove(ant_tuple)
-                                        if uvutils.polstr2num(pol) in polarizations:
-                                            polarizations.remove(uvutils.polstr2num(pol))
+                                        if uvutils.polstr2num(
+                                                pol, x_orientation=self.x_orientation) in polarizations:
+                                            polarizations.remove(
+                                                uvutils.polstr2num(
+                                                    pol, x_orientation=self.x_orientation))
                                     elif not (pol.lower() in pols_data
                                               or pol in warned_pols):
                                         warned_pols.append(pol)
@@ -3442,7 +3472,7 @@ class UVData(UVBase):
             print('\nParsed polarizations:')
             if polarizations is not None:
                 for pol in polarizations:
-                    print(uvutils.polnum2str(pol))
+                    print(uvutils.polnum2str(pol, x_orientation=self.x_orientation))
 
         if len(warned_ants) > 0:
             warnings.warn('Warning: Antenna number {a} passed, but not present '


Test patch:
diff --git a/ci/pyuvdata_min_deps_tests.yml b/ci/pyuvdata_min_deps_tests.yml
index 989595b2..bdc07b83 100644
--- a/ci/pyuvdata_min_deps_tests.yml
+++ b/ci/pyuvdata_min_deps_tests.yml
@@ -8,4 +8,4 @@ dependencies:
   - numpy
   - scipy
   - six
-  - coveralls
+  - coverage
diff --git a/ci/pyuvdata_tests.yml b/ci/pyuvdata_tests.yml
index b373f76a..ef625e39 100644
--- a/ci/pyuvdata_tests.yml
+++ b/ci/pyuvdata_tests.yml
@@ -9,6 +9,7 @@ dependencies:
   - nose
   - numpy
   - python-casacore
+  - pyyaml
   - scipy
   - six
-  - coveralls
+  - coverage
diff --git a/pyuvdata/tests/test_beamfits.py b/pyuvdata/tests/test_beamfits.py
index 731c6a4b..88c6d17b 100644
--- a/pyuvdata/tests/test_beamfits.py
+++ b/pyuvdata/tests/test_beamfits.py
@@ -33,6 +33,7 @@ def test_readCST_writereadFITS():
 
     # add optional parameters for testing purposes
     beam_in.extra_keywords = {'KEY1': 'test_keyword'}
+    beam_in.x_orientation = 'east'
     beam_in.reference_impedance = 340.
     beam_in.receiver_temperature_array = np.random.normal(50.0, 5, size=(beam_in.Nspws, beam_in.Nfreqs))
     beam_in.loss_array = np.random.normal(50.0, 5, size=(beam_in.Nspws, beam_in.Nfreqs))
@@ -61,6 +62,7 @@ def test_readCST_writereadFITS():
 
     # add optional parameters for testing purposes
     beam_in.extra_keywords = {'KEY1': 'test_keyword'}
+    beam_in.x_orientation = 'east'
     beam_in.reference_impedance = 340.
     beam_in.receiver_temperature_array = np.random.normal(50.0, 5, size=(beam_in.Nspws, beam_in.Nfreqs))
     beam_in.loss_array = np.random.normal(50.0, 5, size=(beam_in.Nspws, beam_in.Nfreqs))
@@ -155,6 +157,7 @@ def test_writeread_healpix():
 
     # add optional parameters for testing purposes
     beam_in.extra_keywords = {'KEY1': 'test_keyword'}
+    beam_in.x_orientation = 'east'
     beam_in.reference_impedance = 340.
     beam_in.receiver_temperature_array = np.random.normal(50.0, 5, size=(beam_in.Nspws, beam_in.Nfreqs))
     beam_in.loss_array = np.random.normal(50.0, 5, size=(beam_in.Nspws, beam_in.Nfreqs))
@@ -522,6 +525,7 @@ def test_multi_files():
 
     # add optional parameters for testing purposes
     beam_full.extra_keywords = {'KEY1': 'test_keyword'}
+    beam_full.x_orientation = 'east'
     beam_full.reference_impedance = 340.
     beam_full.receiver_temperature_array = np.random.normal(50.0, 5, size=(beam_full.Nspws, beam_full.Nfreqs))
     beam_full.loss_array = np.random.normal(50.0, 5, size=(beam_full.Nspws, beam_full.Nfreqs))
diff --git a/pyuvdata/tests/test_cst_beam.py b/pyuvdata/tests/test_cst_beam.py
index ce808520..960f9422 100644
--- a/pyuvdata/tests/test_cst_beam.py
+++ b/pyuvdata/tests/test_cst_beam.py
@@ -69,7 +69,8 @@ def test_read_yaml():
     uvtest.checkWarnings(beam1.read_cst_beam, [cst_files],
                          {'beam_type': 'efield', 'telescope_name': 'HERA', 'feed_name': 'Dipole',
                           'feed_version': '1.0', 'model_name': 'Dipole - Rigging height 4.9 m',
-                          'model_version': '1.0', 'reference_impedance': 100,
+                          'model_version': '1.0', 'x_orientation': 'east',
+                          'reference_impedance': 100,
                           'history': 'Derived from https://github.com/Nicolas-Fagnoni/Simulations.'
                           '\nOnly 2 files included to keep test data volume low.',
                           'extra_keywords': extra_keywords},
@@ -93,7 +94,8 @@ def test_read_yaml_override():
     uvtest.checkWarnings(beam1.read_cst_beam, [cst_files],
                          {'beam_type': 'efield', 'telescope_name': 'test', 'feed_name': 'Dipole',
                           'feed_version': '1.0', 'model_name': 'Dipole - Rigging height 4.9 m',
-                          'model_version': '1.0', 'reference_impedance': 100,
+                          'model_version': '1.0', 'x_orientation': 'east',
+                          'reference_impedance': 100,
                           'history': 'Derived from https://github.com/Nicolas-Fagnoni/Simulations.'
                           '\nOnly 2 files included to keep test data volume low.',
                           'extra_keywords': extra_keywords},
@@ -120,7 +122,8 @@ def test_read_yaml_freq_select():
     uvtest.checkWarnings(beam1.read_cst_beam, [cst_files[0]],
                          {'beam_type': 'efield', 'telescope_name': 'HERA', 'feed_name': 'Dipole',
                           'feed_version': '1.0', 'model_name': 'Dipole - Rigging height 4.9 m',
-                          'model_version': '1.0', 'reference_impedance': 100,
+                          'model_version': '1.0', 'x_orientation': 'east',
+                          'reference_impedance': 100,
                           'history': 'Derived from https://github.com/Nicolas-Fagnoni/Simulations.'
                           '\nOnly 2 files included to keep test data volume low.',
                           'extra_keywords': extra_keywords},
@@ -158,7 +161,8 @@ def test_read_yaml_feed_pol_list():
     uvtest.checkWarnings(beam1.read_cst_beam, [cst_files],
                          {'beam_type': 'efield', 'telescope_name': 'HERA', 'feed_name': 'Dipole',
                           'feed_version': '1.0', 'model_name': 'Dipole - Rigging height 4.9 m',
-                          'model_version': '1.0', 'reference_impedance': 100,
+                          'model_version': '1.0', 'x_orientation': 'east',
+                          'reference_impedance': 100,
                           'history': 'Derived from https://github.com/Nicolas-Fagnoni/Simulations.'
                           '\nOnly 2 files included to keep test data volume low.',
                           'extra_keywords': extra_keywords},
@@ -174,7 +178,8 @@ def test_read_yaml_feed_pol_list():
     uvtest.checkWarnings(beam1.read_cst_beam, [cst_files[0]],
                          {'beam_type': 'efield', 'telescope_name': 'HERA', 'feed_name': 'Dipole',
                           'feed_version': '1.0', 'model_name': 'Dipole - Rigging height 4.9 m',
-                          'model_version': '1.0', 'reference_impedance': 100,
+                          'model_version': '1.0', 'x_orientation': 'east',
+                          'reference_impedance': 100,
                           'history': 'Derived from https://github.com/Nicolas-Fagnoni/Simulations.'
                           '\nOnly 2 files included to keep test data volume low.',
                           'extra_keywords': extra_keywords},
@@ -214,7 +219,8 @@ def test_read_yaml_multi_pol():
                         feed_pol=['x', 'y'], telescope_name='HERA',
                         feed_name='Dipole', feed_version='1.0',
                         model_name='Dipole - Rigging height 4.9 m',
-                        model_version='1.0', reference_impedance=100,
+                        model_version='1.0', x_orientation='east',
+                        reference_impedance=100,
                         history='Derived from https://github.com/Nicolas-Fagnoni/Simulations.'
                         '\nOnly 2 files included to keep test data volume low.',
                         extra_keywords=extra_keywords)
@@ -227,7 +233,8 @@ def test_read_yaml_multi_pol():
                         feed_pol=['x', 'y'], telescope_name='HERA',
                         feed_name='Dipole', feed_version='1.0',
                         model_name='Dipole - Rigging height 4.9 m',
-                        model_version='1.0', reference_impedance=100,
+                        model_version='1.0', x_orientation='east',
+                        reference_impedance=100,
                         history='Derived from https://github.com/Nicolas-Fagnoni/Simulations.'
                         '\nOnly 2 files included to keep test data volume low.',
                         extra_keywords=extra_keywords)
diff --git a/pyuvdata/tests/test_utils.py b/pyuvdata/tests/test_utils.py
index 8273f394..e8d52076 100644
--- a/pyuvdata/tests/test_utils.py
+++ b/pyuvdata/tests/test_utils.py
@@ -275,9 +275,54 @@ def test_pol_funcs():
     nt.assert_equal(uvutils.parse_polstr("xX"), 'xx')
     nt.assert_equal(uvutils.parse_polstr("XX"), 'xx')
     nt.assert_equal(uvutils.parse_polstr('i'), 'pI')
-    nt.assert_equal(uvutils.parse_jpolstr('x'), 'Jxx')
-    nt.assert_equal(uvutils.parse_jpolstr('xy'), 'Jxy')
-    nt.assert_equal(uvutils.parse_jpolstr('XY'), 'Jxy')
+
+
+def test_pol_funcs_x_orientation():
+    """ Test utility functions to convert between polarization strings and numbers with x_orientation """
+
+    pol_nums = [-8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4]
+
+    x_orient1 = 'e'
+    pol_str = ['ne', 'en', 'nn', 'ee', 'lr', 'rl', 'll', 'rr', 'pI', 'pQ', 'pU', 'pV']
+    nt.assert_equal(pol_nums, uvutils.polstr2num(pol_str, x_orientation=x_orient1))
+    nt.assert_equal(pol_str, uvutils.polnum2str(pol_nums, x_orientation=x_orient1))
+    # Check individuals
+    nt.assert_equal(-6, uvutils.polstr2num('NN', x_orientation=x_orient1))
+    nt.assert_equal('pV', uvutils.polnum2str(4))
+    # Check errors
+    nt.assert_raises(KeyError, uvutils.polstr2num, 'foo', x_orientation=x_orient1)
+    nt.assert_raises(ValueError, uvutils.polstr2num, 1, x_orientation=x_orient1)
+    nt.assert_raises(ValueError, uvutils.polnum2str, 7.3, x_orientation=x_orient1)
+    # Check parse
+    nt.assert_equal(uvutils.parse_polstr("eE", x_orientation=x_orient1), 'ee')
+    nt.assert_equal(uvutils.parse_polstr("xx", x_orientation=x_orient1), 'ee')
+    nt.assert_equal(uvutils.parse_polstr("NN", x_orientation=x_orient1), 'nn')
+    nt.assert_equal(uvutils.parse_polstr("yy", x_orientation=x_orient1), 'nn')
+    nt.assert_equal(uvutils.parse_polstr('i', x_orientation=x_orient1), 'pI')
+
+    x_orient2 = 'n'
+    pol_str = ['en', 'ne', 'ee', 'nn', 'lr', 'rl', 'll', 'rr', 'pI', 'pQ', 'pU', 'pV']
+    nt.assert_equal(pol_nums, uvutils.polstr2num(pol_str, x_orientation=x_orient2))
+    nt.assert_equal(pol_str, uvutils.polnum2str(pol_nums, x_orientation=x_orient2))
+    # Check individuals
+    nt.assert_equal(-6, uvutils.polstr2num('EE', x_orientation=x_orient2))
+    nt.assert_equal('pV', uvutils.polnum2str(4))
+    # Check errors
+    nt.assert_raises(KeyError, uvutils.polstr2num, 'foo', x_orientation=x_orient2)
+    nt.assert_raises(ValueError, uvutils.polstr2num, 1, x_orientation=x_orient2)
+    nt.assert_raises(ValueError, uvutils.polnum2str, 7.3, x_orientation=x_orient2)
+    # Check parse
+    nt.assert_equal(uvutils.parse_polstr("nN", x_orientation=x_orient2), 'nn')
+    nt.assert_equal(uvutils.parse_polstr("xx", x_orientation=x_orient2), 'nn')
+    nt.assert_equal(uvutils.parse_polstr("EE", x_orientation=x_orient2), 'ee')
+    nt.assert_equal(uvutils.parse_polstr("yy", x_orientation=x_orient2), 'ee')
+    nt.assert_equal(uvutils.parse_polstr('i', x_orientation=x_orient2), 'pI')
+
+    # check warnings for non-recognized x_orientation
+    nt.assert_equal(uvtest.checkWarnings(uvutils.polstr2num, ['xx'], {'x_orientation': 'foo'},
+                                         message='x_orientation not recognized'), -5)
+    nt.assert_equal(uvtest.checkWarnings(uvutils.polnum2str, [-6], {'x_orientation': 'foo'},
+                                         message='x_orientation not recognized'), 'yy')
 
 
 def test_jones_num_funcs():
@@ -299,6 +344,69 @@ def test_jones_num_funcs():
     nt.assert_raises(ValueError, uvutils.jstr2num, 1)
     nt.assert_raises(ValueError, uvutils.jnum2str, 7.3)
 
+    # check parse method
+    nt.assert_equal(uvutils.parse_jpolstr('x'), 'Jxx')
+    nt.assert_equal(uvutils.parse_jpolstr('xy'), 'Jxy')
+    nt.assert_equal(uvutils.parse_jpolstr('XY'), 'Jxy')
+
+
+def test_jones_num_funcs_x_orientation():
+    """ Test utility functions to convert between jones polarization strings and numbers with x_orientation"""
+
+    jnums = [-8, -7, -6, -5, -4, -3, -2, -1]
+    x_orient1 = 'east'
+    jstr = ['Jne', 'Jen', 'Jnn', 'Jee', 'Jlr', 'Jrl', 'Jll', 'Jrr']
+    nt.assert_equal(jnums, uvutils.jstr2num(jstr, x_orientation=x_orient1))
+    nt.assert_equal(jstr, uvutils.jnum2str(jnums, x_orientation=x_orient1))
+    # Check shorthands
+    jstr = ['ne', 'en', 'nn', 'n', 'ee', 'e', 'lr', 'rl', 'll', 'l', 'rr', 'r']
+    jnums = [-8, -7, -6, -6, -5, -5, -4, -3, -2, -2, -1, -1]
+    nt.assert_equal(jnums, uvutils.jstr2num(jstr, x_orientation=x_orient1))
+    # Check individuals
+    nt.assert_equal(-6, uvutils.jstr2num('jnn', x_orientation=x_orient1))
+    nt.assert_equal('Jen', uvutils.jnum2str(-7, x_orientation=x_orient1))
+    # Check errors
+    nt.assert_raises(KeyError, uvutils.jstr2num, 'foo', x_orientation=x_orient1)
+    nt.assert_raises(ValueError, uvutils.jstr2num, 1, x_orientation=x_orient1)
+    nt.assert_raises(ValueError, uvutils.jnum2str, 7.3, x_orientation=x_orient1)
+
+    # check parse method
+    nt.assert_equal(uvutils.parse_jpolstr('e', x_orientation=x_orient1), 'Jee')
+    nt.assert_equal(uvutils.parse_jpolstr('x', x_orientation=x_orient1), 'Jee')
+    nt.assert_equal(uvutils.parse_jpolstr('y', x_orientation=x_orient1), 'Jnn')
+    nt.assert_equal(uvutils.parse_jpolstr('en', x_orientation=x_orient1), 'Jen')
+    nt.assert_equal(uvutils.parse_jpolstr('NE', x_orientation=x_orient1), 'Jne')
+
+    jnums = [-8, -7, -6, -5, -4, -3, -2, -1]
+    x_orient2 = 'north'
+    jstr = ['Jen', 'Jne', 'Jee', 'Jnn', 'Jlr', 'Jrl', 'Jll', 'Jrr']
+    nt.assert_equal(jnums, uvutils.jstr2num(jstr, x_orientation=x_orient2))
+    nt.assert_equal(jstr, uvutils.jnum2str(jnums, x_orientation=x_orient2))
+    # Check shorthands
+    jstr = ['en', 'ne', 'ee', 'e', 'nn', 'n', 'lr', 'rl', 'll', 'l', 'rr', 'r']
+    jnums = [-8, -7, -6, -6, -5, -5, -4, -3, -2, -2, -1, -1]
+    nt.assert_equal(jnums, uvutils.jstr2num(jstr, x_orientation=x_orient2))
+    # Check individuals
+    nt.assert_equal(-6, uvutils.jstr2num('jee', x_orientation=x_orient2))
+    nt.assert_equal('Jne', uvutils.jnum2str(-7, x_orientation=x_orient2))
+    # Check errors
+    nt.assert_raises(KeyError, uvutils.jstr2num, 'foo', x_orientation=x_orient2)
+    nt.assert_raises(ValueError, uvutils.jstr2num, 1, x_orientation=x_orient2)
+    nt.assert_raises(ValueError, uvutils.jnum2str, 7.3, x_orientation=x_orient2)
+
+    # check parse method
+    nt.assert_equal(uvutils.parse_jpolstr('e', x_orientation=x_orient2), 'Jee')
+    nt.assert_equal(uvutils.parse_jpolstr('x', x_orientation=x_orient2), 'Jnn')
+    nt.assert_equal(uvutils.parse_jpolstr('y', x_orientation=x_orient2), 'Jee')
+    nt.assert_equal(uvutils.parse_jpolstr('en', x_orientation=x_orient2), 'Jen')
+    nt.assert_equal(uvutils.parse_jpolstr('NE', x_orientation=x_orient2), 'Jne')
+
+    # check warnings for non-recognized x_orientation
+    nt.assert_equal(uvtest.checkWarnings(uvutils.jstr2num, ['x'], {'x_orientation': 'foo'},
+                                         message='x_orientation not recognized'), -5)
+    nt.assert_equal(uvtest.checkWarnings(uvutils.jnum2str, [-6], {'x_orientation': 'foo'},
+                                         message='x_orientation not recognized'), 'Jyy')
+
 
 def test_conj_pol():
     """ Test function to conjugate pols """
diff --git a/pyuvdata/tests/test_uvbeam.py b/pyuvdata/tests/test_uvbeam.py
index 674b2630..0d26edb8 100644
--- a/pyuvdata/tests/test_uvbeam.py
+++ b/pyuvdata/tests/test_uvbeam.py
@@ -60,6 +60,7 @@ class TestUVBeamInit(object):
                                  '_extra_keywords', '_Nelements',
                                  '_element_coordinate_system',
                                  '_element_location_array', '_delay_array',
+                                 '_x_orientation',
                                  '_interpolation_function', '_freq_interp_kind',
                                  '_gain_array', '_coupling_matrix',
                                  '_reference_impedance',
@@ -74,6 +75,7 @@ class TestUVBeamInit(object):
                                  'basis_vector_array', 'extra_keywords', 'Nelements',
                                  'element_coordinate_system',
                                  'element_location_array', 'delay_array',
+                                 'x_orientation',
                                  'interpolation_function', 'freq_interp_kind',
                                  'gain_array', 'coupling_matrix',
                                  'reference_impedance',
diff --git a/pyuvdata/tests/test_uvcal.py b/pyuvdata/tests/test_uvcal.py
index f85d76f3..79d4dd2f 100644
--- a/pyuvdata/tests/test_uvcal.py
+++ b/pyuvdata/tests/test_uvcal.py
@@ -1407,3 +1407,26 @@ class TestUVCalAddDelay(object):
                                                 self.delay_object.history))
         self.delay_object.history = delay_object_full.history
         nt.assert_equal(self.delay_object, delay_object_full)
+
+
+def test_deprecated_x_orientation():
+    cal_in = UVCal()
+    testfile = os.path.join(DATA_PATH, 'zen.2457698.40355.xx.gain.calfits')
+    cal_in.read_calfits(testfile)
+
+    cal_in.x_orientation = 'e'
+
+    uvtest.checkWarnings(cal_in.check, category=PendingDeprecationWarning,
+                         message=['x_orientation e is not one of [east, north], '
+                                  'converting to "east".'])
+
+    cal_in.x_orientation = 'N'
+    uvtest.checkWarnings(cal_in.check, category=PendingDeprecationWarning,
+                         message=['x_orientation N is not one of [east, north], '
+                                  'converting to "north".'])
+
+    cal_in.x_orientation = 'foo'
+    nt.assert_raises(ValueError, uvtest.checkWarnings, cal_in.check,
+                     category=PendingDeprecationWarning,
+                     message=['x_orientation n is not one of [east, north], '
+                              'cannot be converted.'])
diff --git a/pyuvdata/tests/test_uvdata.py b/pyuvdata/tests/test_uvdata.py
index f4f37e55..9116b22a 100644
--- a/pyuvdata/tests/test_uvdata.py
+++ b/pyuvdata/tests/test_uvdata.py
@@ -2477,7 +2477,48 @@ def test_get_pols():
                          message='Telescope EVLA is not')
     pols = uv.get_pols()
     pols_data = ['rr', 'll', 'lr', 'rl']
-    nt.assert_count_equal(pols, pols_data)
+    nt.assert_equal(sorted(pols), sorted(pols_data))
+
+
+def test_get_pols_x_orientation():
+    miriad_file = os.path.join(DATA_PATH, 'zen.2456865.60537.xy.uvcRREAA')
+    uv_in = UVData()
+    uvtest.checkWarnings(uv_in.read, [miriad_file], known_warning='miriad')
+
+    uv_in.x_orientation = 'east'
+
+    pols = uv_in.get_pols()
+    pols_data = ['en']
+    nt.assert_equal(pols, pols_data)
+
+    uv_in.x_orientation = 'north'
+
+    pols = uv_in.get_pols()
+    pols_data = ['ne']
+    nt.assert_equal(pols, pols_data)
+
+
+def test_deprecated_x_orientation():
+    miriad_file = os.path.join(DATA_PATH, 'zen.2456865.60537.xy.uvcRREAA')
+    uv_in = UVData()
+    uvtest.checkWarnings(uv_in.read, [miriad_file], known_warning='miriad')
+
+    uv_in.x_orientation = 'e'
+
+    uvtest.checkWarnings(uv_in.check, category=PendingDeprecationWarning,
+                         message=['x_orientation e is not one of [east, north], '
+                                  'converting to "east".'])
+
+    uv_in.x_orientation = 'N'
+    uvtest.checkWarnings(uv_in.check, category=PendingDeprecationWarning,
+                         message=['x_orientation N is not one of [east, north], '
+                                  'converting to "north".'])
+
+    uv_in.x_orientation = 'foo'
+    nt.assert_raises(ValueError, uvtest.checkWarnings, uv_in.check,
+                     category=PendingDeprecationWarning,
+                     message=['x_orientation n is not one of [east, north], '
+                              'cannot be converted.'])
 
 
 def test_get_feedpols():
@@ -2489,7 +2530,7 @@ def test_get_feedpols():
                          message='Telescope EVLA is not')
     pols = uv.get_feedpols()
     pols_data = ['r', 'l']
-    nt.assert_count_equal(pols, pols_data)
+    nt.assert_equal(sorted(pols), sorted(pols_data))
 
     # Test break when pseudo-Stokes visibilities are present
     uv.polarization_array[0] = 1  # pseudo-Stokes I