Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Echelle improvements #54

Merged
merged 51 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
88d00dd
Added code relevant to processing echelle weekly report.
emcangi Jun 7, 2023
b480422
Typographical changes to be (mostly) compliant with PEP8
emcangi Jun 8, 2023
c4ef62a
Moved metadata functions back to the echelle file
emcangi Jun 8, 2023
315beab
Minor updates to download module to fix a problem where spaces in the…
emcangi Aug 8, 2023
fb03c11
Significant updates to include echelle quicklook code, as well as som…
emcangi Aug 8, 2023
d2211f0
Mostly cosmetic edits to alphabetize functions and improve some varia…
emcangi Aug 8, 2023
70c525b
Alphabetized function appearance, added some small functions which cr…
emcangi Aug 8, 2023
ef9b288
Added two auxiliary functions to assist with plot making.
emcangi Aug 8, 2023
821801b
Upgraded the detector_image function to be inclusive of l1a files; no…
emcangi Aug 8, 2023
8349f04
Improved sorting of functions, added code to draw lines delineating t…
emcangi Aug 10, 2023
f797b8d
Improved function sorting
emcangi Aug 10, 2023
4c2eaa1
Added a method to return Ls, and turned off memmap, which caused eche…
emcangi Aug 10, 2023
e04e879
Changed source for MCP_VOLT from Observation hdu to Primary header, a…
emcangi Aug 25, 2023
2a9e526
Improved a variable name for clarity in search.py
emcangi Aug 25, 2023
a1ac2a3
Added the ability to run quicklooks for all files after a certain orb…
emcangi Aug 25, 2023
600706f
Reorganized functions according to best practices (main functions on …
emcangi Aug 25, 2023
cb7632a
Added the ability to make quicklooks for any file occurring later tha…
emcangi Sep 8, 2023
2525052
Merge branch 'master' into echelle
emcangi Oct 19, 2023
9ff3f91
Improved downselect_data to more intuitively handle dates and times; …
emcangi Oct 19, 2023
9882759
Improved search using regular expressions for orbit string in pathnam…
emcangi Oct 19, 2023
afdf799
Merge remote-tracking branch 'origin/echelle' into echelle
emcangi Oct 19, 2023
f67ec8c
Fixed a comment that incorrectly stated that a dictionary object was …
emcangi Oct 19, 2023
497c12c
Following commit 9ff3f91a, removed 'andlater' argument from orbit fil…
emcangi Oct 20, 2023
cd16221
Improvements to quicklooks plots
emcangi Oct 20, 2023
23cb498
Corrected an incorrect variable name (wrong scope)
emcangi Oct 23, 2023
ca73150
Improvements to show NaN values, fully NaN frames, and saturated/brok…
emcangi Oct 25, 2023
c4d827b
Quicklook improvements:
emcangi Jan 10, 2024
93d9fa8
Reverting f797b8d which involved shuffling code around and is polluti…
emcangi Jan 30, 2024
8232124
Manual revert of code organization changes from f797b8d in download.p…
emcangi Jan 30, 2024
73ff058
Further reverting the alphabetization of functions that was introduce…
emcangi Jan 30, 2024
2e510ed
Remove nan_color as graphics.py has an appropriate color dictionary.
emcangi Feb 5, 2024
6467166
Move routines to more appropriate modules; add one binning-related ro…
emcangi Feb 5, 2024
c361af4
Move geometry-plotting routines to graphics.py and echelle-specific g…
emcangi Feb 5, 2024
bf5ed3a
Replace accidentally-deleted code which checks if vm is in list of kn…
emcangi Feb 5, 2024
ecdef50
Add tqdm (used in echelle quicklook code) to package requirements in …
emcangi Feb 5, 2024
1669a94
Obtain product data level from filename and assign DN arrays accordin…
emcangi Feb 5, 2024
19ff4ea
Factor out detector plotting code to allow for calling by routines fo…
emcangi Feb 5, 2024
ae415e4
Improve routines related to coadding and dark subtraction, plus creat…
emcangi Feb 5, 2024
d81b483
Cleanup: Typo corrections, filling out Parameter entries left blank, …
emcangi Feb 5, 2024
713fe25
Allow fontsizes parameter to be passed in to quicklook code.
emcangi Feb 6, 2024
1fd9de2
Move exception handling for case where there no valid light frames to…
emcangi Feb 8, 2024
0170b4e
Rename ech_slit_start and ech_slit_end to include reference to Ly alp…
emcangi Feb 9, 2024
48e969a
Allow axes objects to be optional for geometry plots (SZA, tangent po…
emcangi Feb 9, 2024
8e993bb
Move call to retrieve darks into subtract_darks, out of coadd_lights.
emcangi Feb 9, 2024
07835d0
Remove redundant force_vmin and force_vmax which are functionally the…
emcangi Feb 9, 2024
b72c88c
Move get_avg_pixel_count_rate to integration.py
emcangi Feb 9, 2024
d3828f0
Fix small coding error that was breaking the top-level quicklook code
emcangi Feb 9, 2024
bcddfdf
Modify get_dark_frames to return a 3D array of darks to allow for lat…
emcangi Feb 9, 2024
ced635c
Replace IUVSFITS with regular astropy.io.fits objects;
emcangi Feb 9, 2024
5c91dd7
Add imports to integration.py that were missed but necessary for b72c…
emcangi Feb 10, 2024
686b229
Replace code that obtains data level from the filename using split() …
emcangi Feb 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions maven_iuvs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
from . import constants
from . import integration
from . import file_classes
from . import binning
from . import echelle


try:
from .user_paths import auto_spice_load as _auto_spice_load
Expand Down
133 changes: 133 additions & 0 deletions maven_iuvs/binning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import numpy as np

def get_binning_scheme(hdul):
"""
Gets the binning scheme for a given FITS HDU.

Parameters
----------
hdul : astropy FITS HDUList object
HDU list for a given observation

Returns
-------
Dicionaries explaining the binning scheme:
if nonlinear, returns the bin table, along with the number of spatial and spectral bins.
if linear, returns the first spatial and spectral bin edges, the widths, and the number of bins.

"""
if hdul['PRIMARY'].header['NAXIS'] == 1:
nspa = 0
nspe = 0
else:
nspe = hdul['PRIMARY'].header['NAXIS1']
nspa = hdul['PRIMARY'].header['NAXIS2']

bintbl = hdul['PRIMARY'].header['BIN_TBL']
if 'NON LINEAR' in bintbl:
return {'bintbl':bintbl,'nspa':nspa, 'nspe':nspe}

spebinwidth = hdul['PRIMARY'].header['SPE_SIZE']
spabinwidth = hdul['PRIMARY'].header['SPA_SIZE']

spepix0 = hdul['PRIMARY'].header['SPE_OFS']
spapix0 = hdul['PRIMARY'].header['SPA_OFS']

return {'spapix0':spapix0, 'spabinwidth':spabinwidth, 'nspa':nspa,
'spepix0':spepix0, 'spebinwidth':spebinwidth, 'nspe':nspe,}


def pix_to_bin(hdul, pix0, pix1, spa_or_spe, return_npix=True):
"""
Converts pixels to bins on the detector in either the spatial or
spectral dimenison.

Parameters
----------
hdul : astropy FITS HDUList object
HDU list for a given observation
pix0 : int
Lowest pixel number in the given dimension to include
pix1 : int
Highest pixel number in the given dimension to include
spa_or_spe : string
indicates whether this function will convert spatial or
spectral pixels to bins
return_npix : boolean
whether to return the total number of pixels calculated

Returns
-------
binlo : int
Index of lowest bin encompassed by [pix0, pix1] in pixels

binhi : int
Index of highest bin encompassed by [pix0, pix1] in pixels
npix : int
number of total pixels in the enclosed bins

"""
binpixlo = hdul['Binning'].data[spa_or_spe+'PIXLO'][0]
binpixhi = hdul['Binning'].data[spa_or_spe+'PIXHI'][0]
binpixwidth = binpixhi+1 - binpixlo
nbins = len(binpixlo)
binlo = np.searchsorted(binpixlo, pix0+0.01) - 1
binlo = 0 if binlo < 0 else binlo
binhi = np.searchsorted(binpixhi, pix1-0.01) + 1
binhi = nbins if binhi > nbins else binhi

if return_npix:
npix = np.sum(binpixwidth[binlo:binhi])
return binlo, binhi, npix

return binlo, binhi


def get_pix_range(myfits, which="spatial"):
"""
Given a fits observation, gets the range of pixels
for either the spatial or spectral dimension.

Parameters
----------
myfits : IUVSFITS or astropy FITS HDUList object
IUVS FITS file in question
which: string
"spatial" or "spectral"

Returns
----------
Array of pixel values for bin edges.
"""
pixlo = myfits['Binning'].data[f'{which[:3]}pixlo'][0]
pixhi = myfits['Binning'].data[f'{which[:3]}pixhi'][0]

if not (set((pixhi[:-1]+1)-pixlo[1:]) == {0}):
raise ValueError("Error in bin table")

pixrange = np.concatenate([[pixlo[0]], pixhi+1])

return pixrange


def get_npix_per_bin(myfits):
"""Calculates total pixels per bin.

Parameters
----------
myfits: astropy FITS HDUList object
IUVS observation data file

Returns
----------
npixperbin : int
number of pixels per bin
"""
spapixrange = get_pix_range(myfits, which="spatial")
spepixrange = get_pix_range(myfits, which="spectral")

spepixwidth = spepixrange[1:]-spepixrange[:-1]
spapixwidth = spapixrange[1:]-spapixrange[:-1]

npixperbin = np.outer(spapixwidth, spepixwidth)
return npixperbin
29 changes: 16 additions & 13 deletions maven_iuvs/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ def setup_user_paths():

Notes
-------

This is an interactive routine called once, generally the first
time the user calls sync_data.

Expand Down Expand Up @@ -131,11 +130,13 @@ def setup_user_paths():
user_paths_file.write("iuvs_vm_username = \""+vm_username+"\"\n")
user_paths_file.write("auto_spice_load = "+auto_spice_load+"\n")
user_paths_file.close()
# now scripts can import the relevant directories from user_paths

# now scripts can import the relevant directories from user_paths


def get_default_data_directory(level='l1b'):
"""Returns default l1b_dir defined in user_paths.py, creating the
"""
emcangi marked this conversation as resolved.
Show resolved Hide resolved
Returns default l1b_dir defined in user_paths.py, creating the
file if needed.

Parameters
Expand Down Expand Up @@ -170,7 +171,6 @@ def get_default_data_directory(level='l1b'):

return local_dir


def call_rsync(remote_path,
local_path,
ssh_password,
Expand Down Expand Up @@ -219,9 +219,9 @@ def call_rsync(remote_path,
progress_flag = '--progress'

# Add some code to handle a case where spaces in the local folder path will cause rsync to fail silently
if " " in local_dir:
local_dir = local_dir.replace(" ", "\ ")
if " " in local_path:
local_path = local_path.replace(" ", "\ ")

rsync_command = " ".join(['rsync -trvzL',
progress_flag,
extra_flags,
Expand All @@ -236,6 +236,7 @@ def call_rsync(remote_path,
cpl = child.compile_pattern_list([pexpect.EOF,
'.* password: ',
'[0-9]+%'])

while True:
i = child.expect_list(cpl, timeout=None)
if i == 0: # end of file
Expand Down Expand Up @@ -431,8 +432,8 @@ def sync_data(spice=True, level='l1b',
Returns
-------
None.

"""

# setup search pattern
pattern = get_filename_glob_string(**filename_kwargs)

Expand Down Expand Up @@ -482,10 +483,11 @@ def sync_data(spice=True, level='l1b',
else:
raise ValueError('local_dir must be l1a or l1b')

# Check to be sure that the vm is in the known_hosts file.
emcangi marked this conversation as resolved.
Show resolved Hide resolved
# Check to be sure that the vm is in the known_hosts file.
is_vm_found = subprocess.run(["ssh-keygen", "-H", "-F", vm], capture_output=True)
if (is_vm_found.returncode == 1) or ("found" not in is_vm_found.stdout.decode('utf-8')):
raise Exception(f"{vm} is not in the list of known_hosts. Please manually connect via ssh; upon first connection, it will be added automatically to ~./.ssh/known_hosts.")
raise Exception(f"{vm} is not in the list of known_hosts. Please manually connect"
" via ssh; upon first connection, it will be added automatically to ~./.ssh/known_hosts.")

# try to sync the files, if it fails, user probably isn't on the VPN
try:
Expand All @@ -505,6 +507,7 @@ def sync_data(spice=True, level='l1b',
# sync level 1B data
if level is not None:
# get the file names of all the relevant files
print(f"Running sync on {datetime.datetime.utcnow().strftime('%a %d %b %Y, %I:%M%p')}")
print('Fetching names of production and stage'
' files from the VM...')
prod_filenames = get_vm_file_list(vm,
Expand Down Expand Up @@ -780,7 +783,8 @@ def get_integrated_reports_dir():


def sync_integrated_reports(sdc_username, sdc_password, check_old=False):
"""Sync Integrated Reports data from MAVEN Ops page. Syncs all new
"""
Sync Integrated Reports data from MAVEN Ops page. Syncs all new
files and all files from last 180 days by default.

Parameters
Expand All @@ -796,7 +800,6 @@ def sync_integrated_reports(sdc_username, sdc_password, check_old=False):
Returns
-------
none

"""

print("syncing Integrated Reports... ")
Expand Down Expand Up @@ -899,4 +902,4 @@ def sync_sdc(check_old=False):
password = getpass('password for '+username+' on MAVEN Team SDC: ')

sync_euvm_l2b(username, password)
sync_integrated_reports(username, password, check_old=check_old)
sync_integrated_reports(username, password, check_old=check_old)
Loading