GithubHelp home page GithubHelp logo

spacetelescope / pysiaf Goto Github PK

View Code? Open in Web Editor NEW
13.0 11.0 28.0 56.3 MB

Handling of Science Instrument Aperture Files (SIAF) for space telescopes

Home Page: https://pysiaf.readthedocs.io

License: BSD 3-Clause "New" or "Revised" License

Python 100.00%
python stsci astrometry aperture focal-plane

pysiaf's Introduction

Build Status Documentation Status PyPI version PyPI - License DOI

pysiaf

Handling of Science Instrument Aperture Files (SIAF) for space telescopes. SIAF files contain detailed geometric focal plane descriptions and relationships for the science instruments. They are maintained in the JWST/HST PRD (Project Reference Database).
pysiaf is a python package to access, interpret, maintain, and generate SIAF, in particular for JWST. Tools for applying the frame transformations, plotting, comparison, and validation are provided.

Functionalities

  • Captures current PRD content, i.e. pysiaf includes a copy of the SIAF XML files. These are maintained to be synchronized with the PRD.
  • Transformations between the SIAF frames (Detector, Science, Ideal, Telelescope/V) are pre-loaded and easily accessible.
  • Tools for plotting, validation, and comparison of SIAF apertures and files.
  • Support for implementing transformations between celestial (RA, Dec) and telescope/V (V2, V3) coordinate systems is provided.
  • Input/output: reading SIAF XML, writing XML/Excel/csv etc.
  • Captures SI source data and code to generate the SIAF apertures
  • Standard python package with installation script, unit tests, documentation.
  • Supports working with HST SIAF (read-only).

Example usage

Check which PRD version is in use:
print(pysiaf.JWST_PRD_VERSION)

Frame transformations (det, sci, idl, tel are supported frames):

    import pysiaf
    instrument = 'NIRISS'

    # read SIAFXML
    siaf = pysiaf.Siaf(instrument)  

    # select single aperture by name
    nis_cen = siaf['NIS_CEN']  

    # access SIAF parameters
    print('{} V2Ref = {}'.format(nis_cen.AperName, nis_cen.V2Ref))
    print('{} V3Ref = {}'.format(nis_cen.AperName, nis_cen.V3Ref))

    for attribute in ['InstrName', 'AperShape']:
        print('{} {} = {}'.format(nis_cen.AperName, attribute, getattr(nis_cen, attribute)))


    # coordinates in Science frame
    sci_x = np.array([0, 2047, 2047, 0])
    sci_y = np.array([0, 0, 2047, 2047])  

    # transform from Science frame to Ideal frame
    idl_x, idl_y = nis_cen.sci_to_idl(sci_x, sci_y)

Plotting (only a small subset of options is illustrated):

    import matplotlib.pyplot as plt

    plt.figure(figsize=(4, 4), facecolor='w', edgecolor='k'); plt.clf()

    # plot single aperture
    nis_cen.plot()

    # plot all apertures in SIAF
    for aperture_name, aperture in siaf.apertures.items():
        aperture.plot()
    plt.show()
    # plot 'master' apertures
    from pysiaf.siaf import plot_master_apertures
    plt.figure(figsize=(8, 8), facecolor='w', edgecolor='k'); plt.clf()
    plot_master_apertures(mark_ref=True)
    plt.show()
    # plot HST apertures
    siaf = pysiaf.Siaf('HST')
    aperture_names = ['FGS1', 'FGS2', 'FGS3', 'IUVIS1FIX', 'IUVIS2FIX', 'JWFC1FIX', 'JWFC2FIX']

    plt.figure(figsize=(4, 4), facecolor='w', edgecolor='k')
    for aperture_name in aperture_names:
        siaf[aperture_name].plot(color='r', fill_color='darksalmon', mark_ref=True)
    ax = plt.gca()
    ax.set_aspect('equal')
    ax.invert_yaxis()
    plt.show()

Documentation

The primary reference for a description of JWST SIAF is Cox & Lallo, 2017, JWST-STScI-001550: Description and Use of the JWST Science Instrument Aperture File, available at https://jwst.stsci.edu/documentation/technical-documents.

pysiaf is documented at https://pysiaf.readthedocs.io/

Citation

If you find this package useful, please consider citing the Zenodo record using the DOI badge above. Please find additional citation instructions in CITATION.

Disclaimer

All parameter values in pysiaf are subject to change. JWST values are preliminary until the JWST observatory commissioning has concluded.

Distortion and other transformations in pysiaf are of sufficient accuracy for operations, but do not necessarily have science-grade quality. For instance, generally only one filter solution is carried per aperture. For science-grade transformations, please consult the science pipelines and their reference files (see https://jwst-docs.stsci.edu/jwst-data-reduction-pipeline)

For science observation planning, the focal plane geometry implemented in the latest APT (http://www.stsci.edu/hst/proposing/apt) takes precedence.
The STScI Telescopes Branch provides full support of pysiaf for S&OC operational systems only.

Contributing

Please open a new issue or new pull request for bugs, feedback, or new features you would like to see. If there is an issue you would like to work on, please leave a comment and we will be happy to assist. New contributions and contributors are very welcome!
Do you have feedback and feature requests? Is there something missing you would like to see? Please open an issue or send an email to the maintainers. This package follows the Space Telescope Code of Conduct strives to provide a welcoming community to all of our users and contributors.

The following describes the typical work flow for contributing to the pysiaf project (adapted from JWQL): 0. Do not commit any sensitive information (e.g. STScI-internal path structures, machine names, user names, passwords, etc.) to this public repository. Git history cannot be erased.

  1. Create a fork off of the spacetelescope pysiaf repository on your personal github space.
  2. Make a local clone of your fork.
  3. Ensure your personal fork is pointing upstream to https://github.com/spacetelescope/pysiaf
  4. Open an issue on spacetelescope pysiaf that describes the need for and nature of the changes you plan to make. This is not necessary for minor changes and fixes.
  5. Create a branch on that personal fork.
  6. Make your software changes.
  7. Push that branch to your personal GitHub repository, i.e. to origin.
  8. On the spacetelescope pysiaf repository, create a pull request that merges the branch into spacetelescope:master.
  9. Assign a reviewer from the team for the pull request.
  10. Iterate with the reviewer over any needed changes until the reviewer accepts and merges your branch.
  11. Delete your local copy of your branch.

Installation

This package is supported in python 3.8 and 3.9

pip install pysiaf

Clone the repository:
git clone https://github.com/spacetelescope/pysiaf
Install pysiaf:
cd pysiaf
pip install .

Install in Develop Mode pip install -e .

Known installation issues

If you get an error upon
import pysiaf
that traces back to
import lxml.etree as ET
and states
ImportError [...] Library not loaded: libxml2.2.dylib Reason: Incompatible library version: etree.[...] requires version 12.0.0 or later, but libxml2.2.dylib provides version 10.0.0,
this can probably be fixed by downgrading the version of lxml, e.g.
pip uninstall lxml
pip install lxml==3.6.4

pyqt5 installation issues: If using MacOS Mojave, it causes matplotlib to fail without pyqt5. Please take appropriate action to make sure pyqt5 is installed for

pysiaf's People

Contributors

charlesrp avatar colinrcox avatar drlaw1558 avatar goudfroo avatar jastansberry avatar jhunkeler avatar jneu avatar johannes-sahlmann avatar marthaboyer avatar mfixstsci avatar mgennaro avatar mperrin avatar rendinam avatar shanosborne avatar sosey avatar stscieisenhamer avatar tonysohn avatar tracy-beck avatar witchblade101 avatar zacharyburnett avatar zanecodes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pysiaf's Issues

dependency on pytest at runtime

setup.py does not list pytest as a requirement. However, pysiaf can't be imported without it. This is because pysiaf/__init__.py imports tests.test_aperture, which in turn imports pysiaf.

It's not clear to me why pysiaf would require having the test_aperture functions imported at all times (as opposed to just when testing). Seems to me that we could just remove the import of test_aperture from __init__.py. But I'll wait to discuss this with Johannes.

For now, since this is a roadblock to releasing the next version of webbpsf reliably, I think I'm going to just add pytest as a requirement to webbpsf to work around this.

Message on destination folder for diagnostic plots

It could be useful to provide the user of generate_NIRCam.py and the other generate*.py scripts with help output messages stating where the output plots are located on the local system.
Initially I wasn't able to find mine.

Also note that plots will be put by default in the main installation directory of pysiaf, not the current working directory. Not sure this is the most desirable setup. In particular, if pysiaf is not installed in dev mode, the installation directory will be somewhere like
username/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf-0.5.1-py3.5.egg/pysiaf/ and user might have difficulty finding the diagnostic plots (unless a message is implemented)

Verify AperType before plotting

I tried to run plot_all_apertures(showchannels=False, showorigin=True) and I got TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe'' when it got to NIRSpec's CLEAR_GWA_OTE aperture. I believe this is because the V3IdlYAngle variable is NoneType for this aperture which caused an error on line 779 in aperture.py (although I don't know why the value is None).

NIRSpec reference_point and corners functions not working

Hello:

While the ap.reference_point and ap.corners function seem to work fine for NIRISS, they don't seem to be working with NIRSpec. I can do reference_point('tel'), but reference_point('det') fails, as does any use of the corners function with nirspec. Is this a known issue?

I've cut and pasted some output from tests with jupyter-notebooks below.

Thanks,
Charles

nrs_siaf = pysiaf.Siaf('NIRSpec')
nrs_a1600 = nrs_siaf['NRS_S1600A1_SLIT']
print(nrs_a1600.reference_point('tel'))
print(nrs_a1600.reference_point('det'))
WARNING: NIRSPEC transformations may be unreliable
(321.531952, -473.679199)
WARNING: NIRSPEC transformations may be unreliable

AttributeError Traceback (most recent call last)
in ()
2 nrs_a1600 = nrs_siaf['NRS_S1600A1_SLIT']
3 print(nrs_a1600.reference_point('tel'))
----> 4 print(nrs_a1600.reference_point('det'))

~/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf/aperture.py in reference_point(self, to_frame)
614 def reference_point(self, to_frame):
615 """ Return the defining reference point of the aperture."""
--> 616 return self.convert(self.V2Ref, self.V3Ref, 'tel', to_frame)
617
618 # Definition of frame transforms

~/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf/aperture.py in convert(self, X, Y, from_frame, to_frame)
330 '{}to{}'.format(from_frame.lower(), to_frame.lower()))
331
--> 332 return conversion_method(X, Y)
333
334 def correct_for_dva(self, v2_arcsec, v3_arcsec, verbose=False):

~/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf/aperture.py in tel_to_det(self, *args)
904
905 def tel_to_det(self, *args):
--> 906 return self.sci_to_det(*self.idl_to_sci(*self.tel_to_idl(*args)))
907
908 def raw_to_sci(self, x_raw, y_raw):

~/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf/aperture.py in idl_to_sci(self, x_idl, y_idl, filter_name)
1623 """
1624 v2, v3 = self.idl_to_tel(x_idl, y_idl)
-> 1625 x_sci, y_sci = self.tel_to_sci(v2, v3, filter_name=filter_name)
1626 return x_sci, y_sci
1627

~/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf/aperture.py in tel_to_sci(self, x_tel, y_tel, filter_name)
1686 x_ote_deg, y_ote_deg = x_an/3600., y_an/3600.
1687
-> 1688 x_gwa_out, y_gwa_out = self.ote_to_gwa(x_ote_deg, y_ote_deg, filter_name=filter_name)
1689 x_gwa_in, y_gwa_in = self.gwaout_to_gwain(x_gwa_out, y_gwa_out)
1690 x_sci, y_sci = self.gwa_to_sci(x_gwa_in, y_gwa_in)

~/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf/aperture.py in ote_to_gwa(self, ote_x, ote_y, filter_name)
1556 'Filter must be one of {} (it is {})'.format(filter_list, filter_name))
1557
-> 1558 transform_aperture = getattr(self, '_{}_GWA_OTE'.format(filter_name))
1559 X_model, Y_model = transform_aperture.distortion_transform('idl', 'sci', include_offset=False)
1560 return X_model(ote_x, ote_y), Y_model(ote_x, ote_y)

AttributeError: 'NirspecAperture' object has no attribute '_CLEAR_GWA_OTE'

In [13]:
nis_siaf = pysiaf.Siaf('NIRISS')
nis_cen = nis_siaf['NIS_CEN']
print(nis_cen.corners('idl'))
nrs_siaf = pysiaf.Siaf('NIRSpec')
nrs_a1600 = nrs_siaf['NRS_S1600A1_SLIT']
print(nrs_a1600.corners('idl'))

(array([-66.90772149, 66.97059667, 66.97801059, -66.94589561]), array([-67.11461178, -67.78806669, 67.11658772, 67.67969208]))

TypeError Traceback (most recent call last)
in ()
4 nrs_siaf = pysiaf.Siaf('NIRSpec')
5 nrs_a1600 = nrs_siaf['NRS_S1600A1_SLIT']
----> 6 print(nrs_a1600.corners('idl'))

~/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf/aperture.py in corners(self, to_frame, rederive)
392 if rederive or not hasattr(self, 'XIdlVert1'):
393 # see Colin's Calc worksheet
--> 394 x1 = -1 * getattr(self, 'XSciRef') + 0.5
395 x2 = -1 * getattr(self, 'XSciRef') + 0.5 + getattr(self, 'XSciSize')
396 y1 = -1 * getattr(self, 'YSciRef') + 0.5

TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'

Siaf aperture definition error for NRCA1_GRISMTS

I've come across what I think is an error in the aperture definitions for the NRCA1_GRISMTS apertures. The parent_apertures for these cases appear to be incorrect. Below is an example of the problem I am seeing:

import pysiaf
from pysiaf import iando
siaf = pysiaf.Siaf('nircam')
aperture = 'NRCA1_GRISMTS128'
aperture_check = siaf[aperture]
siaf_aperture_definitions = iando.read.read_siaf_aperture_definitions('nircam')
index = siaf_aperture_definitions['AperName'].tolist().index(aperture)
aperture_check._parent_apertures = siaf_aperture_definitions['parent_apertures'][index]
print(aperture_check._parent_apertures)
>   'NRCA1_FULL; NRCA5_GRISM128_F444W'

When I run the case above using the NRCA3_GRISMTS128 aperture, the parent aperture is NRCA3_FULL, as expected. Perhaps the semi-colon after NRCA1_FULL is the problem? I see the same error for all 3 of the NRCA1_GRISMTS apertures.

error when running generate_nircam

I am getting the following error:

Apertures with significant roundtrip error differences:
AperName siaf0_metric siaf0_dx_mean siaf0_dy_mean siaf0_dx_rms ... difference_dx_mean difference_dy_mean difference_dx_rms difference_dy_rms
-------- ------------ ------------- ------------- ------------ ... ------------------ ------------------ ----------------- -----------------
Traceback (most recent call last):
  File "generate_nircam.py", line 356, in <module>
    ref_siaf = pysiaf.Siaf(instrument, filename=os.path.join(pre_delivery_dir, 'NIRCam_SIAF_outdated.xml'))
  File "/Users/gennaro/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf-0.5.1-py3.5.egg/pysiaf/siaf.py", line 293, in __init__
    self.apertures = read.read_jwst_siaf(self.instrument, filename=filename, basepath=basepath)
  File "/Users/gennaro/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf-0.5.1-py3.5.egg/pysiaf/iando/read.py", line 400, in read_jwst_siaf
    tree = ET.parse(filename)
  File "src/lxml/lxml.etree.pyx", line 3442, in lxml.etree.parse (src/lxml/lxml.etree.c:81716)
  File "src/lxml/parser.pxi", line 1811, in lxml.etree._parseDocument (src/lxml/lxml.etree.c:118635)
  File "src/lxml/parser.pxi", line 1837, in lxml.etree._parseDocumentFromURL (src/lxml/lxml.etree.c:118982)
  File "src/lxml/parser.pxi", line 1741, in lxml.etree._parseDocFromFile (src/lxml/lxml.etree.c:117894)
  File "src/lxml/parser.pxi", line 1138, in lxml.etree._BaseParser._parseDocFromFile (src/lxml/lxml.etree.c:112440)
  File "src/lxml/parser.pxi", line 595, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:105896)
  File "src/lxml/parser.pxi", line 706, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:107604)
  File "src/lxml/parser.pxi", line 633, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:106415)
OSError: Error reading file '/Users/gennaro/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf-0.5.1-py3.5.egg/pysiaf/pre_delivery_data/NIRCam/NIRCam_SIAF_outdated.xml': failed to load external entity "/Users/gennaro/anaconda3/envs/astroconda/lib/python3.5/site-packages/pysiaf-0.5.1-py3.5.egg/pysiaf/pre_delivery_data/NIRCam/NIRCam_SIAF_outdated.xml"

Any recommendations on how to solve it? Looks like a file "NIRCam_SIAF_outdated.xml" is missing.

Broken labels in aperture.plot()

(@shanosborne asked me to open an issue for this.) I have been using pysiaf's plotting ability in one of my notebooks for a while now, like so:

nc_siaf = pysiaf.Siaf('NIRCam')

plt.figure(figsize=(15,10))
for apername in sorted(nc_siaf.apernames):
    a = apername
    if ('_FULL' in a) and ('OSS' not in a) and ('MASK' not in a) and (a[-1] != 'P'):
        nc_siaf[a].plot(frame='tel', name_label=True, fill_color='white')
plt.gca().invert_xaxis()

However, with the latest updates of pysiaf (not sure if it was 0.2.4 or 0.2.5 or something else), the name_label=True parameter doesn't seem to be working as expected anymore. Instead of turning on the name labels for each aperture in the plot, now all the name labels are displaying as "True".

When I tried label=True instead of name_label=True, I got a legend over the plot that listed every aperture on the plot being labeled as "True".

In this specific example I can get the behavior I want (the aperture names appearing as colored text in the plot) by setting name_label=a, but it seems to me like the labelling shouldn't work this way.

convert method fails for HST apertures

I was trying to convert coordinates for the HST apertures, and pysiaf fails. This is what I did:

import pysiaf
hst=pysiaf.Siaf('HST')
uvis1=hst['IUVIS1']
uvis1.convert(1,1,'sci','det')

The traceback is very long, but the last stanza gives:

~/miniconda3/envs/astroconda37/lib/python3.7/site-packages/pysiaf/aperture.py in linear_transform_model(from_system, to_system, parity, angle_deg)
   2017     if type(angle_deg) not in [int, float, np.float64, np.int64]:
   2018         raise TypeError('Angle has to be a float. It is of type {} and has the value {}'.format(
-> 2019             type(angle_deg), angle_deg))
   2020 
   2021     # check for allowed system pairs

TypeError: Angle has to be a float. It is of type <class 'NoneType'> and has the value None

This is running:
pysiaf.version
'0.7.1'

I did this with the JWST apertures, and things seemed to work. Any advice here? Is this a issue with the HST reference files?

Unable to install pysiaf in astroconda environment

Pysiaf does not install correctly when starting from an astroconda environment. Using conda version 4.5.11 I created a completely new astroconda environment with python 3.6 from the stable channel (http://ssb.stsci.edu/astroconda):
conda create -n myenv stsci python=3.6

By default, lxml is installed like so:

> conda list lxml
# Name                    Version                   Build  Channel
lxml                      4.2.5            py36hef8c89e_0

Doing a pip install pysiaf gives me the following versions of lxml and pysiaf:

# Name                    Version                   Build  Channel
pysiaf                    0.2.4                     <pip>
lxml                      4.2.5            py36hef8c89e_0  

But when importing pysiaf I get the error warned about in the pysiaf README:

Reason: Incompatible library version: etree.cpython-36m-darwin.so requires version 12.0.0 or later, but libxml2.2.dylib provides version 10.0.0

I follow the instructions to uninstall and install lxml version 3.6.4. Now I get

# Name                    Version                   Build  Channel
pysiaf                    0.2.4                     <pip>
lxml                      3.6.4                     <pip>

as expected.

Yet still pysiaf won't import, and throws the same error as before.

The only solution I have found is to uninstall both pysiaf and lxml and then install pysiaf. When I do this I get identical versions to the original attempt:

# Name                    Version                   Build  Channel
pysiaf                    0.2.4                     <pip>
lxml                      4.2.5                     <pip>

with the only difference being that lxml is now coming from pip and not conda. For some reason pysiaf imports fine like this. I really don't understand how the pip vs. conda versions of lxml 4.2.5 are different. I can't tell if this actually solved some underlying problem or is just a surface-level fix.

Additionally, it should be noted that doing a conda install pysiaf does not give you the same version of pysiaf as pip install pysiaf. conda install gives you 0.1.8 while pip install gives you 0.2.4...

Update the help

Tyler Desjardins mentions that we should consider moving emails from help[at]stsci.edu to point to the web portal where possible and appropriate. For HST (or any non-JWST), it is https://hsthelp.stsci.edu . For JWST, it is https://jwsthelp.stsci.edu . Please update info in setup.py, setup.cfg, documentation, etc as appropriate.

Please close this issue if it is irrelevant to your repository. This is an automated issue. If this is opened in error, please let pllim know!

xref spacetelescope/hstcal#317

Remove scipy dependency

scipy is used only in one single function of polynomial.polyfit.

The use of scipy.linalg.solve should be replaced by np.linalg.solve abe pysiaf's dependency on scipy should be removed.

generate_nirspec.py failing with TypeError

Running generate_nirspec.py errors with the following traceback:

Loading reference files from directory: /Users/sosborne/repos/pysiaf/pysiaf/source_data/NIRSpec/delivery

  =============================================%

/Users/sosborne/repos/pysiaf/pysiaf/source_data/NIRSpec/delivery/delivery_SCA491toGWA.pcf
2016/6/16

Order 5 21  terms

 /Users/sosborne/repos/pysiaf/pysiaf/source_data/NIRSpec/delivery/delivery_SCA491toGWA.pcf
A
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-49d4545cdb06> in <module>
----> 1 import generate_nirspec

~/repos/pysiaf/generate/generate_nirspec.py in <module>
    703 for field in pcf_file_mapping.keys():
    704     pcf_data[field] = {}
--> 705     pcf_data[field]['A'], pcf_data[field]['B'], pcf_data[field]['C'], pcf_data[field]['D'] = reorder(os.path.join(source_data_dir, pcf_file_mapping[field]), verbose=True)
    706 
    707 # reference file delivered by IDT

~/repos/pysiaf/generate/generate_nirspec.py in reorder(pcfName, verbose)
    441         print('\n', pcfName)
    442         print('A')
--> 443         polynomial.print_triangle(A2, order=5)
    444         print('\nB')
    445         polynomial.print_triangle(B2, order=5)

TypeError: print_triangle() got an unexpected keyword argument 'order'

Fix Siaf.list_apertures()

In [14]: s.list_apertures()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-14-49d7a832c5e9> in <module>()
----> 1 s.list_apertures()

~/jwst/code/github/spacetelescope/pysiaf/pysiaf/siaf.py in list_apertures(self, instrument, shape)
     65     def list_apertures(self, instrument=None, shape=None):
     66         """Print a list of apertures to screen."""
---> 67         idx1 = range(len(self.toc))
     68         idx2 = range(len(self.toc))
     69         if instrument is not None:

AttributeError: 'Siaf' object has no attribute 'toc'

version information not being set correctly by installation from PyPI

The version on PyPI is somehow not setting the package version information correctly:

(astroconda) mperrin@phoenix python3.6/site-packages  > pip install pysiaf
Collecting pysiaf
Downloading https://files.pythonhosted.org/packages/a3/ac/d46815bbea01538ea07d35e27c1763f87fabac09a962593ca0f22bf2149d/pysiaf-0.1.8.tar.gz (26.2MB)
[...  lots of log messages ...]
Successfully built pysiaf
Installing collected packages: pysiaf
Successfully installed pysiaf-0.0.0

This also results in no version information after import:

In [1]: import pysiaf

In [2]: pysiaf.__version__
Out[2]: '0.0.0'

Need to add option for off-nominal GWA tilts to NIRSpec transforms

NIRSpec SIAF transforms that cross the Grating Wheel Assembly Mirror should take
optional arguments gwa_ytil and gwa_xtil that are used to specify the GWA sensor
positions. If these are not specified gwa_ytil should default to rx0 as defined
in the SIAF gwa transform rows, while gwa_xtil should default to ry0

The coefficients AX, AY, rx0, and ry0 as read from the SIAF file columns
XSciScale, YSciScale, XSciRef, and YSciRef in the GWA_OTE transform rows.

The user should normally just specify something like either xsci, ysci =
nrs1.tel_to_sci(v2,v3) as they do now to get the default tilts, or xsci, ysci =
nrs1.tel_to_sci(v2,v3, gwa_ytil=value1, gwa_xtil=value2 ) and have the supplied
coefficients used in any transformation that crosses the GWA. If the input
coordinates are arrays of values, the gwa_ytil and gwa_xtil should be able to
take either single scalar values or matching length arrays.

It should be allowed to supply tilt values for any NIRSpec transform, although
of course it will only have an effect on transforms that cross the GWA.

A version of the transformation equations in both directions taken from python
code written by Maria Pena and based on IDL code from Tony Keyes is given below.
The original equations are based on NTN-2014-005/ESA-JWST-TN-21403 "Geometrical
transforms for NIRSpec target acquisition" by G. Giardino, P. Ferruit, C. Alves
de Oliveira These have the advantage that they've been tested for both
directions, although the notation does vary from that needed in pysiaf.

The sample code below hard-wires the SIAF coefficients in as defaults. In the actual pysiaf code these should of course be set up to simply use the SIAF table values, and the tilt parameters
should default to the values that yield zero for delta theta (gwa_xtil defaults to ry0 and
gwa_ytil defaults to rx0). Other changes to this code will be needed to conform to pysiaf naming
and conventions.

def gwain_to_gwaout(xgwa_in, ygwa_in, gwa_xtil, gwa_ytil, ax=4260.830, ay=-9108.782, rx0=0.196614012122, ry0=0.347495883703):
''' Implementation of reflection in GWA pupil plane accross mirror as a function of the GWA tilt sensor angles
This is for the direction from the detector towards the sky, where xgwa/ygwa is the coordinate system before
the reflection, while xgwa_out/ygwa_out is the coordinate system after the reflection. The equations here are valid
in the small angle approximation and are based on NTN-2014-005/ESA-JWST-TN-21403 Geometrical transforms for
NIRSpec target acquisition by G. Giardino, P. Ferruit, C. Alves de Oliveira.
For this test code we are supplying specific default values for the SIAF coefficients. In production code these
should be taken from the SIAF file. Also in production code, gwa_xtil, if not specified, should default to ry0
and gwa_ytil to rx0 (note the x/y swap in these definitions.)

inputs: xgwa - mirror rotation angle in 'X' direction (units arc-sec)
        ygwa - mirror rotation angle in 'Y' direction  (units arc-sec)
        gwa_xtil (units mV) - gwa_xtil telemetry measurement
        gwa_ytil (units mV) - gwa_ytil telemetry measurement
        ax (arc-sec/mV)  - from XSciScale column in GWA_OTE transform rows
        ay (arc-sec/mV)  - from YSciScale column in GWA_OTE transform rows
        rx0 (mV)  # nominal GWA sensor value - from XSciRef in GWA_OTE rows
        ry0 (mV)  # nominal GWA sensor value - from YSciRef in GWA_OTE rows
outputs: xgwa_out, ygwa_out - GWA angular coordinates after reflection and rotation.

initial IDL version - T. Keyes 2015
initial python version M. Pena-Guerrero 2015 in ct_forward function in coords_transform.py in nirspec_TA module
revised C. Proffitt 2018 to isolate gwa transforms and simplify code and notation.
'''  
delta_theta_x = 0.5 * ax * (gwa_ytil - rx0) * np.pi / (180. * 3600.0)
delta_theta_y = 0.5 * ay * (gwa_xtil - ry0) * np.pi / (180. * 3600.0)

# calculate direction cosines of xgwa, ygwa
v = np.abs(np.sqrt(1.0 + xgwa*xgwa + ygwa*ygwa))
x0 = xgwa_in / v
y0 = ygwa_in / v
z0 = 1.0 / v
# rotate to mirror reference system with small angle approx. and perform rotation
x1 = -1 * (x0 - delta_theta_y * np.sqrt(1.0 - x0*x0 - (y0+delta_theta_x*z0)*(y0+delta_theta_x*z0)))
y1 = -1 * (y0 + delta_theta_x * z0)
z1 = np.sqrt(1.0 - x1*x1 - y1*y1)
# rotate reflected ray back to ref GWA coord system with small angle approx., 
# but first with an inverse rotation around the y-axis
x2 = x1 + delta_theta_y * z1
y2 = y1
z2 = np.sqrt(1.0 - x2*x2 - y2*y2)
# now do an inverse rotation around the x-axis
x3 = x2
y3 = y2 - delta_theta_x * z2     
z3 = np.sqrt(1.0 - x3*x3 - y3*y3)
# compute the cosines from direction cosines
xgwa_out = x3 / z3
ygwa_out = y3 / z3

return xgwa_out, ygwa_out

def gwaout_to_gwain(xgwa_out, ygwa_out, gwa_xtil, gwa_ytil, ax=4260.830, ay=-9108.782, rx0=0.196614012122, ry0=0.347495883703):

delta_theta_x = 0.5 * ax * (gwa_ytil - rx0) * np.pi / (180. * 3600.0)
delta_theta_y = 0.5 * ay * (gwa_xtil - ry0) * np.pi / (180. * 3600.0)

# calculate direction cosines of xt, yt, (xgwa, ygwa)   
v = np.abs(np.sqrt(1.0 + xgwa_out*xgwa_out + ygwa_out*ygwa_out))
x3 = xgwa_out / v
y3 = ygwa_out / v
z3 = 1.0 / v
# do inverse rotation around the x-axis
x2 = x3
y2 = y3 + delta_theta_x*z3
z2 = np.sqrt(1.0 - x2*x2 - y2*y2)
# rotate to mirror reference system with small angle approx. and perform rotation
x1 = x2 - delta_theta_y*z2 # try changing - to +???
y1 = y2
z1 = np.sqrt(1.0 - x1*x1 - y1*y1)
# rotate reflected ray back to reference GWA coordinate system (use small angle approx.),
# first with an inverse rotation around the y-axis:
x0 = -1.0*x1 + delta_theta_y * np.sqrt(1.0 - x1*x1 - (y1+delta_theta_x*z1)*(y1+delta_theta_x*z1))
y0 = -1.0*y1 - delta_theta_x*z1
z0 = np.sqrt(1.0 - x0*x0 - y0*y0)

xgwa_in = x0/z0
ygwa_in = y0/z0

return xgwa_in, ygwa_in

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.