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

Effective area channel object #169

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3f759c4
Testing commit using a sting
joyvelasquez Jul 20, 2023
a05d5bf
Created a class for EffectiveArea
joyvelasquez Aug 14, 2023
348f089
Adding a function for validating users requested observation date
joyvelasquez Aug 14, 2023
a6c247a
Creating the effective area function in Channel
joyvelasquez Aug 14, 2023
b78391f
Adding observation_date function to change dates/testing for now.
joyvelasquez Aug 14, 2023
d5b3ea1
Adding EffectiveArea as a function in Channel.py
joyvelasquez Aug 14, 2023
f2267f9
Adding EffectiveArea
joyvelasquez Aug 16, 2023
663a811
Adding the EffectiveArea class to all
joyvelasquez Aug 16, 2023
0ff4775
Creating a new function, observation_date
joyvelasquez Aug 17, 2023
e527a40
Correcting effective area in the channel class
joyvelasquez Aug 17, 2023
d5381ac
Importing functions from xrtpy.util.time to be used in Effective area
joyvelasquez Aug 17, 2023
f484339
Updated observation_date to include a single task and provide more in…
joyvelasquez Aug 17, 2023
b5575af
Updated method of calcuation and doc. in xrt_data_time_to_dt function
joyvelasquez Aug 17, 2023
ee8009f
Creating a new function : validating_data_observation_date - Validate…
joyvelasquez Aug 17, 2023
b2a3d1c
Built validating_data_observation_date function to validate the reque…
joyvelasquez Aug 17, 2023
f74bb28
Adding new functions to __all__
joyvelasquez Aug 17, 2023
a5ed090
Removiing comments
joyvelasquez Aug 17, 2023
d860063
Renaming the observation_date function to validate_observation_date
joyvelasquez Aug 17, 2023
ce9a484
Importing functions from xrtpy.util.time into channel
joyvelasquez Aug 17, 2023
63c3b77
Updating validating_observation_date function to reference correct fu…
joyvelasquez Aug 18, 2023
db7b4cb
Updated EffectiveArea function to require observation date.
joyvelasquez Aug 18, 2023
4505ac7
Updating code-not sure what
joyvelasquez Aug 31, 2023
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
2 changes: 2 additions & 0 deletions xrtpy/response/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from xrtpy.response.channel import (
CCD,
Channel,
EffectiveArea,
EntranceFilter,
Filter,
Geometry,
Expand All @@ -20,6 +21,7 @@
"Mirror",
"Filter",
"CCD",
"EffectiveArea",
"Channel",
"resolve_filter_name",
"EffectiveAreaFundamental",
Expand Down
78 changes: 77 additions & 1 deletion xrtpy/response/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"Mirror",
"Filter",
"CCD",
"EffectiveArea",
"Channel",
"resolve_filter_name",
]
Expand All @@ -17,6 +18,9 @@
from astropy import units as u
from pathlib import Path

# from xrtpy.response.effective_area import EffectiveAreaFundamental
from xrtpy.util.time import validating_data_observation_date

filename = Path(__file__).parent.absolute() / "data" / "xrt_channels_v0016.genx"

_channel_name_to_index_mapping = {
Expand Down Expand Up @@ -335,6 +339,69 @@ def ccd_wavelength(self) -> u.angstrom:
]


class EffectiveArea:
"""Class for calculating the effective area."""

# import pdb; pdb.set_trace()
# from xrtpy.response.EffectiveAreaFundamental import observation_date

# Add Obs. date.

# Add a requirement when effective area is call.The observation date is required; it is not required for the Channel
# observation_date = "2007-09-22T22:59:59"

def __init__(self, index, observation_date):
self._channel_index = index
self.observation_date = observation_date
# self._channel = Channel(name)
# self._channel = Channel(filter_name)
# self.observation_date = observation_date

@property
def effective_area_filter(self):
# Reverse the dictionary to create an index-to-string mapping
index_to_string = {
value: key for key, value in _channel_name_to_index_mapping.items()
}

# Get the string associated with an index
desired_index = self._channel_index
desired_string = index_to_string.get(desired_index)

if desired_string is not None:
pass
else:
print(f"No string found for index {desired_index}")

return desired_string

@property
def validating_observation_date(self):
"""
Validate a user's requested observation date. Furthermore,
validate the requested observation date against the available data.
"""
return validating_data_observation_date(self.observation_date)

# # import pdb; pdb.set_trace()
# @u.quantity_input
# def effective_area(self): # -> u.cm**2:
# filter = effective_area_filter()
# obs_date = validating_observation_date()
# print(filter, obs_date)
# EffectiveAreaFundamental(filter, obs_date)

# # print(geometry_aperture_area)
# return 1
"""Calculation of the Effective Area."""
# return (
# self.channel_geometry_aperture_area
# * self.channel_transmission
# * self.interpolated_CCD_contamination_transmission
# * self.interpolated_filter_contamination_transmission
# )


class Channel:
"""
XRTpy
Expand All @@ -345,9 +412,10 @@ class Channel:

_genx_file = _genx_file

def __init__(self, name):
def __init__(self, name, observation_date=None):
name = resolve_filter_name(name)
if name in _channel_name_to_index_mapping:
self._name = name # Testing
self._channel_index = _channel_name_to_index_mapping[name]
self._channel_data = _genx_file[self._channel_index]
self._geometry = Geometry(self._channel_index)
Expand All @@ -357,6 +425,10 @@ def __init__(self, name):
self._filter_1 = Filter(self._channel_index, 1)
self._filter_2 = Filter(self._channel_index, 2)
self._ccd = CCD(self._channel_index)
if observation_date is not None:
self._effective_area = EffectiveArea(
self._channel_index, observation_date
)
elif name.lower() == "open": # Complete by adding remaining indices
self._sample_channel_data = _genx_file[1]
self._geometry = Geometry(1)
Expand Down Expand Up @@ -398,6 +470,10 @@ def filter_2(self) -> Filter:
def ccd(self) -> CCD:
return self._ccd

@property
def effective_area(self) -> EffectiveArea:
return self._effective_area

def __str__(self):
"""Readable printout."""
return f"XRT Channel for {self.name}"
Expand Down
156 changes: 142 additions & 14 deletions xrtpy/util/time.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,162 @@
__all__ = [
"epoch",
"validate_observation_date",
"validating_data_observation_date",
]

import astropy.time
import os
import scipy.io
import sunpy.time

from datetime import timedelta
from datetime import datetime, timedelta
from pathlib import Path

# Hinode-XRT mission elapsed time "Epoch" is Sept 22, 2006 21:36:00.
epoch = astropy.time.Time("2006-09-22 21:36:00")


def xrt_data_time_to_dt(data_time, epoch):
# Adding dat up till today UTC time
def xrt_data_time_to_dt(data_time: list, epoch: datetime) -> tuple:
"""
Converting data time (float64) to a datetime object.
Convert data times (float64) to datetime objects and seconds from epoch.

Parameters
----------
data_time : real number (?)
Description...
epoch : `datetime.datetime`
This function will convert the requested date and time into a datetime
object in seconds from the respected launched date to collect the correct date.
data_time : list of float
A list of float values representing data times.
epoch : datetime.datetime
The reference datetime representing the mission epoch.

Returns
-------
tuple
A tuple containing two lists: data dates as datetime objects and
data dates as seconds from the epoch.
"""
data_dates_dt = []
data_dates_seconds = []

t0 = data_time[0] # Initial time

for time in data_time:
t0 = data_time[0]
t1 = time
dt = t1 - t0
data_dates_dt.append(epoch + timedelta(0, dt))
data_dates_seconds.append(float((epoch + timedelta(0, dt)).strftime("%s")))
return (data_dates_dt, data_dates_seconds)
dt = time - t0
data_date_dt = epoch + timedelta(seconds=dt)
data_dates_dt.append(data_date_dt)
data_dates_seconds.append(float(data_date_dt.strftime("%s")))

return data_dates_dt, data_dates_seconds


def validate_observation_date(data_time: str) -> datetime:
"""
Validate a user's requested observation date.

Parameters
----------
data_time : str
A string representing the observation date in a recognized format.

Returns
-------
datetime.datetime
The validated observation date.

Raises
------
ValueError
If the observation date is not after the defined epoch.

Notes
-----
This function is used to validate a user's requested observation date before using
it in functions related to effective area and temperature response functions.

The `epoch` used for validation is defined as September 22, 2006 21:36:00.
"""

observation_date = sunpy.time.parse_time(data_time)

current_utc_datetime = datetime.utcnow()

# import pdb; pdb.set_trace()
if observation_date <= epoch:
raise ValueError(
f"Invalid date: {observation_date.datetime}. "
f"Date must be after {epoch}."
)

if observation_date > current_utc_datetime:
raise ValueError(
f"Invalid date: {observation_date.datetime}. "
f"Date must not be in the future."
)

return observation_date


# Absolute path - Update method
_ccd_contam_filename = Path(
"/Users/jvelasq/Projects/xrtpy/xrtpy/response/data/xrt_contam_on_ccd.geny"
)

# Read the contamination file
_ccd_contam_file = scipy.io.readsav(_ccd_contam_filename)

# CCD contam geny files keys for time and date.
_ccd_contamination_file_time = astropy.time.Time(
_ccd_contam_file["p1"], format="utime", scale="utc"
)


def validating_data_observation_date(data_time):
"""
############* Debating if this function belongs here *#########################
Validate the requested observation date against the available data.

This function checks whether there is data available for the requested observation date.
If the observation date is later than the last modification date of the contamination data file,
it raises a ValueError indicating that no contamination data is available for the requested date.

Parameters
----------
observation_date : `datetime.datetime`
The requested observation date to be validated.

Returns
-------
observation_date : `datetime.datetime`
The validated observation date.

Raises
------
ValueError
If the observation date is later than the last modification date of the contamination data file,
indicating that no contamination data is available for the requested date.

"""

observation_date = validate_observation_date(data_time)

modified_time_path = os.path.getmtime(_ccd_contam_filename)
modified_time = astropy.time.Time(modified_time_path, format="unix")
latest_available_ccd_data = _ccd_contamination_file_time[-1].datetime.strftime(
"%Y/%m/%d"
)

modified_time_datetime = datetime.fromtimestamp(modified_time_path).strftime(
"%Y/%m/%d"
)

if observation_date.datetime > modified_time:
raise ValueError(
"\nNo contamination data is presently available for "
f"{observation_date.datetime}.\n The latest available data is on "
f"{latest_available_ccd_data}.\n Contamination data is "
"updated periodically. The last update was on "
f"{modified_time_datetime}. If this is more "
"than one month ago, please raise an issue at: "
"https://github.com/HinodeXRT/xrtpy/issues/new"
)

return observation_date.datetime