def test_quantity_output(self): q = 500.25*u.day dt = TimeDelta(q) assert dt.to(u.day) == q assert dt.to(u.second).value == q.to_value(u.second) with pytest.raises(u.UnitsError): dt.to(u.m)
def random_times( size, rate, dead_time=TimeDelta(0, format="sec"), return_diff=False, random_state="random-seed", ): """Make random times assuming a Poisson process. This function can be used to test event time series, to have a comparison what completely random data looks like. Can be used in two ways (in either case the return type is `~astropy.time.TimeDelta`): * ``return_delta=False`` - Return absolute times, relative to zero (default) * ``return_delta=True`` - Return time differences between consecutive events. Parameters ---------- size : int Number of samples rate : `~astropy.units.Quantity` Event rate (dimension: 1 / TIME) dead_time : `~astropy.units.Quantity` or `~astropy.time.TimeDelta`, optional Dead time after event (dimension: TIME) return_diff : bool Return time difference between events? (default: no, return absolute times) random_state : {int, 'random-seed', 'global-rng', `~numpy.random.RandomState`} Defines random number generator initialisation. Passed to `~gammapy.utils.random.get_random_state`. Returns ------- time : `~astropy.time.TimeDelta` Time differences (second) after time zero. Examples -------- Example how to simulate 100 events at a rate of 10 Hz. As expected the last event occurs after about 10 seconds. >>> from astropy.units import Quantity >>> from gammapy.time import random_times >>> rate = Quantity(10, 'Hz') >>> times = random_times(size=100, rate=rate, random_state=0) >>> times[-1] <TimeDelta object: scale='None' format='sec' value=9.186484131475076> """ random_state = get_random_state(random_state) dead_time = TimeDelta(dead_time) scale = (1 / rate).to("s").value time_delta = random_state.exponential(scale=scale, size=size) time_delta += dead_time.to("s").value if return_diff: return TimeDelta(time_delta, format="sec") else: time = time_delta.cumsum() return TimeDelta(time, format="sec")
def test_scales_for_delta_scale_is_none(self, scale, op): """T(X) +/- dT(None) or T(X) +/- Quantity(time-like) This is always allowed and just adds JDs, i.e., the scale of the TimeDelta or time-like Quantity will be taken to be X. The one exception is again for X=UTC, where TAI is assumed instead, so that a day is always defined as 86400 seconds. """ dt_none = TimeDelta([0., 1., -1., 1000.], format='sec') assert dt_none.scale is None q_time = dt_none.to('s') dt = self.dt[scale] dt1 = op(dt, dt_none) assert dt1.scale == dt.scale assert allclose_jd(dt1.jd, op(dt.jd, dt_none.jd)) dt2 = op(dt_none, dt) assert dt2.scale == dt.scale assert allclose_jd(dt2.jd, op(dt_none.jd, dt.jd)) dt3 = op(q_time, dt) assert dt3.scale == dt.scale assert allclose_jd(dt3.jd, dt2.jd) t = self.t[scale] t1 = op(t, dt_none) assert t1.scale == t.scale assert allclose_jd(t1.jd, op(t.jd, dt_none.jd)) if op is operator.add: t2 = op(dt_none, t) assert t2.scale == t.scale assert allclose_jd(t2.jd, t1.jd) t3 = op(t, q_time) assert t3.scale == t.scale assert allclose_jd(t3.jd, t1.jd)
def test_timedelta_to_datetime(): td = TimeDelta(1, format='jd') assert td.to_datetime() == timedelta(days=1) td2 = TimeDelta([[1, 2], [3, 4]], format='jd') td = [[timedelta(days=1), timedelta(days=2)], [timedelta(days=3), timedelta(days=4)]] assert np.all(td2.to_datetime() == td)
def test_set_format(self): """ Test basics of setting format attribute. """ dt = TimeDelta(86400.0, format='sec') assert dt.value == 86400.0 assert dt.format == 'sec' dt.format = 'jd' assert dt.value == 1.0 assert dt.format == 'jd' dt.format = 'datetime' assert dt.value == timedelta(days=1) assert dt.format == 'datetime'
def test_delta_day_is_86400_seconds(self, scale): """TimeDelta or Quantity holding 1 day always means 24*60*60 seconds This holds true for all timescales but UTC, for which leap-second days are longer or shorter by one second. """ t = self.t[scale] dt_day = TimeDelta(1., format='jd') q_day = dt_day.to('day') dt_day_leap = t[-1] - t[0] # ^ = exclusive or, so either equal and not UTC, or not equal and UTC assert allclose_jd(dt_day_leap.jd, dt_day.jd) ^ (scale == 'utc') t1 = t[0] + dt_day assert allclose_jd(t1.jd, t[-1].jd) ^ (scale == 'utc') t2 = q_day + t[0] assert allclose_jd(t2.jd, t[-1].jd) ^ (scale == 'utc') t3 = t[-1] - dt_day assert allclose_jd(t3.jd, t[0].jd) ^ (scale == 'utc') t4 = t[-1] - q_day assert allclose_jd(t4.jd, t[0].jd) ^ (scale == 'utc')
def read_event_file( file_path ): """Function to read the event parameters from a file""" if path.isfile( file_path ) == False: print 'Error: Cannot find input file ' + file_path file_lines = open( file_path, 'r' ).readlines() # Parse parameters to convert to standard units: print 'Input parameters:' params = {} for line in file_lines: ( key, value ) = line.replace('\n','').split( '=' ) key = key.lstrip().rstrip() value = str( value ).lstrip().rstrip() if key in [ 'u_o', 't_E', 'M_L', 'D_L', 'D_S', 'phi', 'I_base' ]: value = float(value) if key == 't_E': value = TimeDelta((value * 24.0 * 3600.0),format='sec') elif key == 'M_L': value = constants.M_sun * value elif key == 'D_L' or key == 'D_S': value = value * constants.pc elif key == 'phi': value = ( value * np.pi ) / 180.0 elif key in [ 't_o', 't_obs_start' ]: value = Time( value , format='isot', scale='utc' ) elif key == 'visit_intervals': tlist = value.split(',') value = [] for entry in tlist: value.append( TimeDelta( (float( entry )*3600.0), format='sec' ) ) elif key == 'exposure_sequences': tlist1 = value.split(',') value = [] for entry in tlist1: tlist2 = entry.split(':') sequence = [] for exp in tlist2: sequence.append( TimeDelta( float( exp ), format='sec' ) ) value.append( sequence ) params[key] = value print key, value return params
def test_valid_quantity_operations2(self): """Check that TimeDelta is treated as a quantity where possible.""" t0 = TimeDelta(100000., format='sec') f = 1./t0 assert isinstance(f, u.Quantity) assert f.unit == 1./u.day g = 10.*u.m/u.second**2 v = t0 * g assert isinstance(v, u.Quantity) assert u.allclose(v, t0.sec * g.value * u.m / u.second) q = np.log10(t0/u.second) assert isinstance(q, u.Quantity) assert q.value == np.log10(t0.sec) s = 1.*u.m v = s/t0 assert isinstance(v, u.Quantity) assert u.allclose(v, 1. / t0.sec * u.m / u.s) t = 1.*u.s t2 = t0 * t assert isinstance(t2, u.Quantity) assert u.allclose(t2, t0.sec * u.s ** 2) t3 = [1] / t0 assert isinstance(t3, u.Quantity) assert u.allclose(t3, 1 / (t0.sec * u.s)) # broadcasting t1 = TimeDelta(np.arange(100000., 100012.).reshape(6, 2), format='sec') f = np.array([1., 2.]) * u.cycle * u.Hz phase = f * t1 assert isinstance(phase, u.Quantity) assert phase.shape == t1.shape assert u.allclose(phase, t1.sec * f.value * u.cycle) q = t0 * t1 assert isinstance(q, u.Quantity) assert np.all(q == t0.to(u.day) * t1.to(u.day)) q = t1 / t0 assert isinstance(q, u.Quantity) assert np.all(q == t1.to(u.day) / t0.to(u.day))
def kepler_fits_reader(filename): """ This serves as the FITS reader for KEPLER or TESS files within astropy-timeseries. This function should generally not be called directly, and instead this time series reader should be accessed with the :meth:`~astropy.timeseries.TimeSeries.read` method:: >>> from astropy.timeseries import TimeSeries >>> ts = TimeSeries.read('kplr33122.fits', format='kepler.fits') # doctest: +SKIP Parameters ---------- filename : `str` or `pathlib.Path` File to load. Returns ------- ts : `~astropy.timeseries.TimeSeries` Data converted into a TimeSeries. """ hdulist = fits.open(filename) # Get the lightcurve HDU telescope = hdulist[0].header['telescop'].lower() if telescope == 'tess': hdu = hdulist['LIGHTCURVE'] elif telescope == 'kepler': hdu = hdulist[1] else: raise NotImplementedError( "{} is not implemented, only KEPLER or TESS are " "supported through this reader".format( hdulist[0].header['telescop'])) if hdu.header['EXTVER'] > 1: raise NotImplementedError("Support for {} v{} files not yet " "implemented".format(hdu.header['TELESCOP'], hdu.header['EXTVER'])) # Check time scale if hdu.header['TIMESYS'] != 'TDB': raise NotImplementedError("Support for {} time scale not yet " "implemented in {} reader".format( hdu.header['TIMESYS'], hdu.header['TELESCOP'])) tab = Table.read(hdu, format='fits') # Some KEPLER files have a T column instead of TIME. if "T" in tab.colnames: tab.rename_column("T", "TIME") for colname in tab.colnames: unit = tab[colname].unit # Make masks nan for any column which will turn into a Quantity # later. TODO: remove once we support Masked Quantities properly? if unit and isinstance(tab[colname], MaskedColumn): tab[colname] = tab[colname].filled(np.nan) # Fix units if unit == 'e-/s': tab[colname].unit = 'electron/s' if unit == 'pixels': tab[colname].unit = 'pixel' # Rename columns to lowercase tab.rename_column(colname, colname.lower()) # Filter out NaN rows nans = np.isnan(tab['time'].data) if np.any(nans): warnings.warn(f'Ignoring {np.sum(nans)} rows with NaN times') tab = tab[~nans] # Time column is dependent on source and we correct it here reference_date = Time(hdu.header['BJDREFI'], hdu.header['BJDREFF'], scale=hdu.header['TIMESYS'].lower(), format='jd') time = reference_date + TimeDelta(tab['time'].data) time.format = 'isot' # Remove original time column tab.remove_column('time') return TimeSeries(time=time, data=tab)
def make_test_observation_table( observatory_name="hess", n_obs=10, az_range=Angle([0, 360], "deg"), alt_range=Angle([45, 90], "deg"), date_range=(Time("2010-01-01"), Time("2015-01-01")), use_abs_time=False, n_tels_range=(3, 4), random_state="random-seed", ): """Make a test observation table. Create an observation table following a specific pattern. For the moment, only random observation tables are created. The observation table is created according to a specific observatory, and randomizing the observation pointingpositions in a specified az-alt range. If a *date_range* is specified, the starting time of the observations will be restricted to the specified interval. These parameters are interpreted as date, the precise hour of the day is ignored, unless the end date is closer than 1 day to the starting date, in which case, the precise time of the day is also considered. In addition, a range can be specified for the number of telescopes. Parameters ---------- observatory_name : str, optional Name of the observatory; a list of choices is given in `~gammapy.data.observatory_locations`. n_obs : int, optional Number of observations for the obs table. az_range : `~astropy.coordinates.Angle`, optional Azimuth angle range (start, end) for random generation of observation pointing positions. alt_range : `~astropy.coordinates.Angle`, optional Altitude angle range (start, end) for random generation of observation pointing positions. date_range : `~astropy.time.Time`, optional Date range (start, end) for random generation of observation start time. use_abs_time : bool, optional Use absolute UTC times instead of [MET]_ seconds after the reference. n_tels_range : int, optional Range (start, end) of number of telescopes participating in the observations. random_state : {int, 'random-seed', 'global-rng', `~numpy.random.RandomState`}, optional Defines random number generator initialisation. Passed to `~gammapy.utils.random.get_random_state`. Returns ------- obs_table : `~gammapy.data.ObservationTable` Observation table. """ random_state = get_random_state(random_state) n_obs_start = 1 obs_table = ObservationTable() # build a time reference as the start of 2010 dateref = Time("2010-01-01T00:00:00") dateref_mjd_fra, dateref_mjd_int = np.modf(dateref.mjd) # define table header obs_table.meta["OBSERVATORY_NAME"] = observatory_name obs_table.meta["MJDREFI"] = dateref_mjd_int obs_table.meta["MJDREFF"] = dateref_mjd_fra if use_abs_time: # show the observation times in UTC obs_table.meta["TIME_FORMAT"] = "absolute" else: # show the observation times in seconds after the reference obs_table.meta["TIME_FORMAT"] = "relative" header = obs_table.meta # obs id obs_id = np.arange(n_obs_start, n_obs_start + n_obs) obs_table["OBS_ID"] = obs_id # obs time: 30 min ontime = Quantity(30. * np.ones_like(obs_id), "minute").to("second") obs_table["ONTIME"] = ontime # livetime: 25 min time_live = Quantity(25. * np.ones_like(obs_id), "minute").to("second") obs_table["LIVETIME"] = time_live # start time # - random points between the start of 2010 and the end of 2014 (unless # otherwise specified) # - using the start of 2010 as a reference time for the header of the table # - observations restrict to night time (only if specified time interval is # more than 1 day) # - considering start of astronomical day at midday: implicit in setting # the start of the night, when generating random night hours datestart = date_range[0] dateend = date_range[1] time_start = random_state.uniform(datestart.mjd, dateend.mjd, len(obs_id)) time_start = Time(time_start, format="mjd", scale="utc") # check if time interval selected is more than 1 day if (dateend - datestart).jd > 1.: # keep only the integer part (i.e. the day, not the fraction of the day) time_start_f, time_start_i = np.modf(time_start.mjd) time_start = Time(time_start_i, format="mjd", scale="utc") # random generation of night hours: 6 h (from 22 h to 4 h), leaving 1/2 h # time for the last run to finish night_start = Quantity(22., "hour") night_duration = Quantity(5.5, "hour") hour_start = random_state.uniform( night_start.value, night_start.value + night_duration.value, len(obs_id) ) hour_start = Quantity(hour_start, "hour") # add night hour to integer part of MJD time_start += hour_start if use_abs_time: # show the observation times in UTC time_start = Time(time_start.isot) else: # show the observation times in seconds after the reference time_start = time_relative_to_ref(time_start, header) # converting to quantity (better treatment of units) time_start = Quantity(time_start.sec, "second") obs_table["TSTART"] = time_start # stop time # calculated as TSTART + ONTIME if use_abs_time: time_stop = Time(obs_table["TSTART"]) time_stop += TimeDelta(obs_table["ONTIME"]) else: time_stop = TimeDelta(obs_table["TSTART"]) time_stop += TimeDelta(obs_table["ONTIME"]) # converting to quantity (better treatment of units) time_stop = Quantity(time_stop.sec, "second") obs_table["TSTOP"] = time_stop # az, alt # random points in a portion of sphere; default: above 45 deg altitude az, alt = sample_sphere( size=len(obs_id), lon_range=az_range, lat_range=alt_range, random_state=random_state, ) az = Angle(az, "deg") alt = Angle(alt, "deg") obs_table["AZ"] = az obs_table["ALT"] = alt # RA, dec # derive from az, alt taking into account that alt, az represent the values # at the middle of the observation, i.e. at time_ref + (TIME_START + TIME_STOP)/2 # (or better: time_ref + TIME_START + (TIME_OBSERVATION/2)) # in use_abs_time mode, the time_ref should not be added, since it's already included # in TIME_START and TIME_STOP az = Angle(obs_table["AZ"]) alt = Angle(obs_table["ALT"]) if use_abs_time: obstime = Time(obs_table["TSTART"]) obstime += TimeDelta(obs_table["ONTIME"]) / 2. else: obstime = time_ref_from_dict(obs_table.meta) obstime += TimeDelta(obs_table["TSTART"]) obstime += TimeDelta(obs_table["ONTIME"]) / 2. location = observatory_locations[observatory_name] altaz_frame = AltAz(obstime=obstime, location=location) alt_az_coord = SkyCoord(az, alt, frame=altaz_frame) sky_coord = alt_az_coord.transform_to("icrs") obs_table["RA"] = sky_coord.ra obs_table["DEC"] = sky_coord.dec # positions # number of telescopes # random integers in a specified range; default: between 3 and 4 n_tels = random_state.randint(n_tels_range[0], n_tels_range[1] + 1, len(obs_id)) obs_table["N_TELS"] = n_tels # muon efficiency # random between 0.6 and 1.0 muoneff = random_state.uniform(low=0.6, high=1.0, size=len(obs_id)) obs_table["MUONEFF"] = muoneff return obs_table
import pickle from modules.utils import get_min_and_max_mean from datetime import timedelta from astropy.time import TimeDelta from modules.config import delay, bin_width # delete if the folders do already have files os.system('find output/ -type f -delete') # opening the list of dates with open('UT_data/listofdates.list', 'rb') as f: dates = pickle.load(f) f.close() # we are interested in delays up to 5 hrs delay = TimeDelta(timedelta(hours=delay)).to_value('jd') dates.sort() n_dates = str(len(dates)) no_plot = '-np --no-plot' with_out = '-o --output' spaces = ' ' for i, date in enumerate(dates): print(spaces * 2 + '(' + str(i) + '/' + n_dates + ')') current_file1_path = './UT_data/file1/' + date + '.csv' current_file2_path = './UT_data/file2/' + date + '.csv' min_sampling_period, max_sampling_period = get_min_and_max_mean( current_file1_path, current_file2_path) print('doing corr for date:', date) print('bin =', bin_width, 'times max period') actual_bin = bin_width * max_sampling_period folder_2_output = './output/'
import matplotlib.pyplot as plt import astropy.units as u from astropy.coordinates import SkyCoord from astropy.time import TimeDelta import sunpy.map import sunpy.coordinates from sunpy.io.special import srs from sunpy.time import parse_time from sunpy.net import Fido, attrs as a ############################################################################## # For this example, we will search for and download a single HMI using Fido. start_time = parse_time("2017-01-25") end_time = start_time + TimeDelta(23 * u.hour + 59 * u.minute + 59 * u.second) results = Fido.search( a.Time(start_time, end_time), a.Instrument('HMI') & a.vso.Physobs("LOS_magnetic_field"), a.vso.Sample(60 * u.second)) ############################################################################## # Let's select only the first file, download it and create a map. result = results[0, 0] file_name = Fido.fetch(result) smap = sunpy.map.Map(file_name) ############################################################################## # Download the SRS file. srs_results = Fido.search(a.Time(start_time, end_time), a.Instrument('SRS_TABLE'))
# wait for target to be available while Time.now() < asteroid_main_observation.min_obs_time: wait_time_s = (asteroid_main_observation.min_obs_time-Time.now()).sec telescope.slackdebug('The observation (%s) will start in %d min (at %s)...' % ( asteroid_main_observation.target.getName(), wait_time_s/60, asteroid_main_observation.min_obs_time.iso[:-7])) time.sleep(delay_time) # start observations telescope.slackdebug("Starting observations...") telescope.crackit() calibrationObservations() # get images of target until target reaches max altitude, if it hasn't already doCalibrationObservations = False while Time.now() + TimeDelta(asteroid_calibration_observation_duration_s, format='sec') < asteroid_main_observation.max_alt_time: telescope.slackdebug("Performing main observations for %s..." % (asteroid_main_observation.target.getName())) # check sun, clouds, slit, etc. telescope.checkSun() if telescope.is_cracked: telescope.checkSlit() telescope.checkAlt() telescope.checkClouds() telescope.getImageStacks(asteroid_main_observation, None, False) if asteroid_main_observation.sequence.do_pinpoint: telescope.pinpoint(asteroid_main_observation, False) doCalibrationObservations = True if doCalibrationObservations: calibrationObservations()
def test_insert_timedelta(): tm = TimeDelta([1, 2], format='sec') # Insert a scalar using an auto-parsed string tm2 = tm.insert(1, TimeDelta([10, 20], format='sec')) assert np.all(tm2 == TimeDelta([1, 10, 20, 2], format='sec'))
def get_time_window(tdate,timeDeltaDays): deltaDate = TimeDelta(timeDeltaDays) t1 = (tdate - deltaDate).iso.split(' ')[0].replace('-','') t2 = (tdate + deltaDate).iso.split(' ')[0].replace('-','') return t1,t2
def sunup(daterange): ''' Find out the times when the Sun is up for a given date range. Returns: dictionary of time objects with keys 'taz', 'teq', each being a two-element Time() object, where first time is start (rise) and second is end (set) ''' # Use the 24-h day specified by daterange (i.e. drop the time of day) mjd1 = int(daterange[0].mjd) mjd2 = int(daterange[1].mjd) aa = eovsa_cat.eovsa_array_with_cat() taz_rise = [] teq_rise = [] taz_set = [] teq_set = [] mjd_list = [] for mjd in range(mjd1,mjd2+1): t = Time(mjd,format='mjd') # Add times in 1-min steps up to duration dur (hours) ts = t + TimeDelta(np.arange(0.,24.,1./60.)/24.,format='jd') nt = len(ts) ha = np.zeros(nt) alt = np.zeros(nt) az = np.zeros(nt) lines = [] for i in range(nt): aa.set_jultime(ts[i].jd) lst = aa.sidereal_time() src = aa.cat['Sun'] src.compute(aa) ha[i] = lst - src.ra alt[i] = src.alt az[i] = src.az ha_deg = deg(ha) alt = deg(alt) az_deg = deg2(az) iset_eq = np.where(np.abs(ha_deg - 55.0) < 0.15)[0][0] irise_eq = np.where(np.abs(ha_deg + 55.0) < 0.15)[0][0] trise_eq = ts[irise_eq] tset_eq = ts[iset_eq] if iset_eq < irise_eq: tset_eq += TimeDelta(1,format='jd') for iwindow in np.arange(0.1,0.2,0.01): try: idx, = np.where(np.abs(alt - 10.0) < iwindow) #****Was 0.1 i1 = idx[0] i2 = idx[1] if i2 == i1+1: if len(idx) > 2: i2 = idx[2] else: i2 = 1439 # Transition is at end break except: print 'Window',iwindow,'did not work. Trying again' if alt[i1] < alt[i1+1]: irise_az = i1 iset_az = i2 else: irise_az = i2 iset_az = i1 trise_az = ts[irise_az] tset_az = ts[iset_az] if iset_az < irise_az: tset_az += TimeDelta(1,format='jd') taz_rise.append(trise_az.mjd) taz_set.append(tset_az.mjd) teq_rise.append(trise_eq.mjd) teq_set.append(tset_eq.mjd) mjd_list.append(mjd) return {'date':Time(mjd_list,format='mjd'), 'taz_rise':Time(taz_rise,format='mjd'),'teq_rise':Time(teq_rise,format='mjd'), 'taz_set':Time(taz_set, format='mjd'), 'teq_set':Time(teq_set, format='mjd')}
state = "None" if (psi < total): state = "Total" elif (psi < partial): state = "Partial" elif (psi < penumbral): state = "Penumbral" return state solar_system_ephemeris.set('jpl') t = Time("2019-01-21 0:00:00", scale="utc") interval = TimeDelta(10.0, format='sec') lightTime = TimeDelta(499, format='sec') lastState = 'none' for x in range(6 * 24 * 60 * 60): t = t + interval earth = get_body_barycentric('earth', t) moon = get_body_barycentric('moon', t) sun = get_body_barycentric('sun', t - lightTime) sun = vector(sun - earth) moon = vector(moon - earth) earth = earth - earth state = test(sun, moon)
def setup(self): # Identical to what is used in LeapSeconds.auto_open(). self.good_enough = (iers.LeapSeconds._today() + TimeDelta(180 - iers._none_to_float(iers.conf.auto_max_age), format='jd')) self._auto_open_files = iers.LeapSeconds._auto_open_files.copy()
def _start_observation_worker(self, obs_config, reload=True): """ Start observation on worker node: #. Candidate clustering #. Extraction of filterbank data #. ML classification :param dict obs_config: Observation config :param bool reload: reload service settings (default: True) """ self.logger.info("Starting observation on worker node") # reload config if reload: self.load_config() # create result dir if full processing is enabled if self.full_processing_enabled: try: util.makedirs(obs_config['result_dir']) except Exception as e: self.logger.error("Failed to create results directory") raise OfflineProcessingException("Failed to create result directory: {}".format(e)) # TAB or IAB mode if obs_config['ntabs'] == 1: obs_config['mode'] = 'IAB' trigger_output_file = "{output_dir}/triggers/data/data_00_full.hdf5".format(**obs_config) else: obs_config['mode'] = 'TAB' trigger_output_file = "{output_dir}/triggers/data/data_full.hdf5".format(**obs_config) # wait until end time + delay start_processing_time = Time(obs_config['parset']['task.stopTime']) + TimeDelta(self.delay, format='sec') self.logger.info("Sleeping until {}".format(start_processing_time.iso)) util.sleepuntil_utc(start_processing_time, event=self.stop_event) # fold pulsar if this is beam 0 and a test pulsar is being observed try: source = obs_config['parset']['task.source.name'] ref_beam = int(obs_config['parset']['task.source.beam']) # Requires access to parset if source in self.test_pulsars and (obs_config['beam'] == ref_beam): self.logger.info("Test pulsar detected: {}".format(source)) self._fold_pulsar(source, obs_config) except Exception as e: self.logger.error("Pulsar folding failed: {}".format(e)) # run calibration tools if this is a calibrator scan # these have "drift" in the source name try: source = obs_config['parset']['task.source.name'] if 'drift' in source: # split into actual source name and which beams were scanned name, beam_range = source.split('drift') # parse beam range, can be one beam or start/end beam if len(beam_range) == 2: # one beam drift_beams = [int(beam_range)] elif len(beam_range) == 4: # start and end beam sbeam = int(beam_range[:2]) ebeam = int(beam_range[2:]) drift_beams = range(sbeam, ebeam + 1) else: self.logger.error("Failed to parse beam range for calibrator scan: {}".format(source)) drift_beams = [] # run calibration tools if this is a calibrator scan of this beam if name in self.calibrators and (obs_config['beam'] in drift_beams): self.logger.info("Calibrator scan through this beam detected: {}".format(source)) self._run_calibration_tools(name, obs_config) except Exception as e: self.logger.error("Calibration tools failed: {}".format(e)) # if full processing is disabled, there is nothing more to do if not self.full_processing_enabled: self.logger.info("Full processing disabled - not running further offline processing") return # create trigger directory trigger_dir = "{output_dir}/triggers".format(**obs_config) try: util.makedirs(trigger_dir) except Exception as e: self.logger.error("Failed to create triggers directory") raise OfflineProcessingException("Failed to create triggers directory: {}".format(e)) # change to trigger directory try: os.chdir(trigger_dir) except Exception as e: self.logger.error("Failed to cd to triggers directory {}: {}".format(trigger_dir, e)) # create subdir try: util.makedirs('data') except Exception as e: self.logger.error("Failed to create triggers/data directory") raise OfflineProcessingException("Failed to create triggers/data directory: {}".format(e)) # merge the trigger files self.logger.info("Merging raw trigger files") numcand_raw = self._merge_triggers(obs_config) # Run clustering for each SB in TAB mode if enabled if self.process_sb and obs_config['mode'] == 'TAB': self.logger.info("Clustering candidates in SB mode") tstart = Time.now() # spread the SBs over the allowed number of threads # output grouped pulses file will only be generated by thread including SB00 chunks = np.array_split(range(obs_config['nsynbeams']), self.numthread) numcand_all = np.zeros(self.numthread) filterbank_prefix = "{output_dir}/filterbank/CB{beam:02d}".format(**obs_config) threads = [] self.logger.info("Starting trigger clustering with {} threads".format(self.numthread)) for ind, chunk in enumerate(chunks): # pick the SB range sbmin, sbmax = min(chunk), max(chunk) # create thread thread = threading.Thread(target=self._cluster, args=[obs_config, filterbank_prefix], kwargs={'out': numcand_all, 'sbmin': sbmin, 'sbmax': sbmax, 'ind': ind}) thread.daemon = True threads.append(thread) thread.start() # wait until all are done for thread in threads: thread.join() # gather results if self.process_sb: # each element equal numcand_grouped = int(numcand_all[0]) else: # each element is one TAB numcand_grouped = int(np.sum(numcand_all[numcand_all != -1])) # Run clustering for IAB / each TAB else: self.logger.info("Clustering candidates in {} mode".format(obs_config['mode'])) tstart = Time.now() if obs_config['mode'] == 'IAB': filterbank_file = "{output_dir}/filterbank/CB{beam:02d}.fil".format(**obs_config) numcand_grouped = self._cluster(obs_config, 0, filterbank_file) elif obs_config['mode'] == 'TAB': numcand_all = np.zeros(obs_config['ntabs']) # max numtread tabs per run; so ntabs / numthread chunks n_chunk = int(np.ceil(obs_config['ntabs'] / float(self.numthread))) chunks = np.array_split(range(obs_config['ntabs']), n_chunk) self.logger.info("Starting trigger clustering with {} chunks ""of {} threads".format(n_chunk, self.numthread)) # start the threads for tab_set in chunks: threads = [] for tab in tab_set: filterbank_file = "{output_dir}/filterbank/CB{beam:02d}_{tab:02d}.fil".format(tab=tab, **obs_config) thread = threading.Thread(target=self._cluster, args=[obs_config, filterbank_file], kwargs={'out': numcand_all, 'tab': tab}) thread.daemon = True threads.append(thread) thread.start() # wait until all are done for thread in threads: thread.join() # gather results numcand_grouped = int(np.sum(numcand_all[numcand_all != -1])) tend = Time.now() self.logger.info("Trigger clustering took {}s".format((tend - tstart).sec)) # Create one hdf5 file for entire CB if obs_config['mode'] == 'TAB': self.logger.info("Merging output HDF5 files") numcand_merged = self._merge_hdf5(obs_config, trigger_output_file) # TEMP so that IAB still works else: numcand_merged = 9999 # Run classifier if numcand_merged != 0: self.logger.info("Classifying candidates") output_prefix = self._classify(obs_config, trigger_output_file) else: self.logger.info("No candidates post-merge. Not running classifier") output_prefix = '' # Merge PDFs if numcand_merged > 0: self.logger.info("Merging classifier output files") self._merge_plots(obs_config) else: self.logger.info("No candidates found post-classifier, not creating merged PDF") # Centralize results self.logger.info("Gathering results") kwargs = {'output_prefix': output_prefix, 'data_file': trigger_output_file, 'numcand_raw': numcand_raw, 'numcand_grouped': numcand_grouped} self._gather_results(obs_config, **kwargs) self.logger.info("Finished processing of observation {output_dir}".format(**obs_config)) return
def run_on_event(channel_id, bypass=False, program_ids=[1,2], outdir="forcedphot"): thread_ts = time.time() #response = web_client.chat_postMessage( # channel=channel_id, # text='testing') if not bypass: try: converations = web_client.conversations_list( channel=channel_id ) channel_slack_id = channel_id for converation in converations: for chan in converation.data["channels"]: if chan["name"] == channel_id.replace("#",""): channel_slack_id = chan["id"] delay_thresh = 15.0 payload = web_client.conversations_history( channel=channel_slack_id, oldest=thread_ts-delay_thresh ) except: return if len(payload["messages"]) == 0: return doTrigger, trigger_action, name, ra, dec = False, 'forced', 'ZTF21abinaiu', 310.480103, 11.70041 for mess in payload["messages"]: print(mess) message_ts = float(mess["ts"]) if np.abs(message_ts - thread_ts) > delay_thresh: continue txt = mess['text'] txtsplit = list(filter(None,txt.split(" "))) if len(txtsplit) == 0: continue if txtsplit[0] == "trigger": doTrigger = True if len(txtsplit) == 4: name = txtsplit[1] ra = float(txtsplit[2]) dec = float(txtsplit[3]) user = mess['user'] if not doTrigger: return else: user, message_ts = 'test', thread_ts # options: gp,rp,ip,zs,Y name, ra, dec = 'ZTF21abinaiu', 310.480103, 11.70041 message = [] message.append("Hi <@{0}>! You are interested in forced photometry, right? Let me get right on that for you.".format(user)) message.append('Received request %.1f seconds ago...' % (np.abs(message_ts - thread_ts))) message.append("We are looking into %s for you" % name) web_client.chat_postMessage( channel=channel_id, text="\n".join(message) ) tstart = Time.now() - TimeDelta(100*u.day) tend = Time.now() fig = do_forcephot(outdir, name, ra, dec, tstart.jd, tend.jd, ncpu=1, limit=100, do_mcmc=True, program_ids=program_ids, verbose=False) upload_fig(fig, user, "forced.png", channel_id) message = [] message.append('Forced photometry complete') web_client.chat_postMessage( channel=channel_id, text="\n".join(message) )
sys.exit(1) elif args.gpsstart is not None: try: starttime = Time(args.gpsstart, format='gps', scale='utc') except ValueError: Exception("Could not parse start GPS time: {}".format( args.gpsstart)) else: try: starttime = Time(args.yearstart, format='decimalyear', scale='utc') except ValueError: Exception("Could not parse start year: {}".format(args.yearstart)) # set the time step try: dt = TimeDelta(args.interval * 3600., format='sec') except ValueError: Exception("Could not parse time interval: {}".format(args.interval)) # set the end time try: endtime = Time(starttime.decimalyear + args.nyears, format='decimalyear', scale='utc') + dt except ValueError: Exception("Could not parse total timespan") pos = [] vel = [] acc = []
def fetch(self, qres, path=None, error_callback=None, **kwargs): """ Download a set of results. Parameters ---------- qres : `~sunpy.net.dataretriever.QueryResponse` Results to download. Returns ------- Results Object """ urls = [qrblock.url for qrblock in qres] filenames = [] local_filenames = [] for i, [url, qre] in enumerate(zip(urls, qres)): name = url.split('/')[-1] # temporary fix !!! coz All QRBs have same start_time values day = Time(qre.time.start.strftime('%Y-%m-%d')) + TimeDelta(i*u.day) if name not in filenames: filenames.append(name) if name.endswith('.gz'): local_filenames.append('{}SRS.txt'.format(day.strftime('%Y%m%d'))) else: local_filenames.append(name) # Files to be actually downloaded paths = self._get_full_filenames(qres, filenames, path) # Those files that will be present after get returns local_paths = self._get_full_filenames(qres, local_filenames, path) # remove duplicate urls. This will make paths and urls to have same number of elements. # OrderedDict is required to maintain ordering because it will be zipped with paths later urls = list(OrderedDict.fromkeys(urls)) dobj = Downloader(max_conn=5) for aurl, fname in zip(urls, paths): dobj.enqueue_file(aurl, filename=fname) paths = dobj.download() outfiles = [] for fname, srs_filename in zip(local_paths, local_filenames): name = fname.name past_year = False for i, fname2 in enumerate(paths): fname2 = pathlib.Path(fname2) if fname2.name.endswith('.txt'): continue year = fname2.name.split('_SRS')[0] if year in name: TarFile = tarfile.open(fname2) filepath = fname.parent member = TarFile.getmember('SRS/' + srs_filename) member.name = name TarFile.extract(member, path=filepath) TarFile.close() outfiles.append(fname) past_year = True break if past_year is False: outfiles.append(fname) paths.data = list(map(str, outfiles)) return paths
def __init__(self, downloader, storage, cache_dir, expiry=10 * u.day): self._downloader = downloader self._storage = storage self._cache_dir = Path(cache_dir) self._expiry = expiry if expiry is None else TimeDelta(expiry)
def reduce(telescope, obskey, tstart, tend, nchan, ngate, ntbin, ntw_min, rfi_filter_raw=None, fref=None, dedisperse=None, rfi_filter_power=None, do_waterfall=True, do_foldspec=True, verbose=True): comm = MPI.COMM_WORLD if dedisperse == 'None': dedisperse = None if verbose > 3 and comm.rank == 0: print(telescope, obskey, tstart, tend, nchan, ngate, ntbin, ntw_min, rfi_filter_raw, fref, dedisperse, do_waterfall, do_foldspec, verbose) if dedisperse is not None and fref is None: raise ValueError("Need to give reference frequency to dedisperse to") obs = obsdata() if verbose > 3 and comm.rank == 0: print(obs) # find nearest observation to 'date', # warning if > 1s off requested start time of observation if obskey not in obs[telescope]: # assume it is a date, which may be only good to nearest second obskey = obs[telescope].nearest_observation(obskey) # target of this observation psr = obs[telescope][obskey]['src'] assert psr in obs['psrs'].keys() dm = obs['psrs'][psr]['dm'] if verbose and comm.rank == 0: print("Attempting to open {0}: {1}".format(telescope, obskey)) with obs[telescope].open(obskey, comm=comm) as fh: if verbose and comm.rank == 0: print("Opened files") # nchan = None means data is channelized already, so we get this # property directly from the file if nchan is None: nchan = fh.nchan # ensure requested number of channels is integer multiple of # existing channels if nchan % getattr(fh, 'nchan', 1) != 0: raise ValueError("Can only channelize data to an integer multiple " "of the number of input channels (={0})." .format(fh.nchan)) time0 = fh.time0 tstart = time0 if tstart is None else Time(tstart, scale='utc') if tstart < time0: raise ValueError("Cowardly refusing to analyse with requested " "time {0} before start time {1}." .format(tstart.iso, time0.iso)) if tend is None: tend = obs[telescope][obskey]['tend'] try: tend = Time(tend, scale='utc') dt = tend - tstart except ValueError: dt = TimeDelta(float(tend), format='sec') tend = tstart + dt if verbose and comm.rank == 0: print("Requested time span: {0} to {1}".format(tstart.isot, tend.isot)) phasepol = obs[telescope][obskey].get_phasepol(time0) nt = fh.ntimebins(tstart, tend) ntint = fh.ntint(nchan if fh.nchan == 1 else fh.nchan) # number of samples to combine for waterfall ntw = min(ntw_min, nt*ntint) # number of records to skip if verbose and comm.rank == 0: print("Using start time {0} and phase polynomial {1}" .format(time0.isot, phasepol)) fh.seek(tstart) if verbose and comm.rank == 0: print("Skipped {0} blocks and will fold {1} blocks to cover " "time span {2} to {3}" .format(fh.offset/fh.blocksize, nt, fh.time().isot, fh.time(fh.offset + nt*fh.blocksize).isot)) # set the default parameters to fold # Note, some parameters may be in fh's HDUs, or fh.__getitem__ # but these are overwritten if explicitly sprecified in Folder folder = Folder(fh, nchan=nchan, nt=nt, ntint=ntint, ngate=ngate, ntbin=ntbin, ntw=ntw, dm=dm, fref=fref, phasepol=phasepol, dedisperse=dedisperse, do_waterfall=do_waterfall, do_foldspec=do_foldspec, verbose=verbose, progress_interval=1, rfi_filter_raw=rfi_filter_raw, rfi_filter_power=rfi_filter_power) myfoldspec, myicount, mywaterfall = folder(fh, comm=comm) # end with print("Rank {0} exited with statement".format(comm.rank)) savepref = "{0}{1}_{2}chan{3}ntbin".format(telescope, psr, nchan, ntbin) if do_waterfall: waterfall = np.zeros_like(mywaterfall) comm.Reduce(mywaterfall, waterfall, op=MPI.SUM, root=0) if comm.rank == 0: # waterfall = normalize_counts(waterfall) np.save("{0}waterfall_{1}+{2:08}sec.npy" .format(savepref, tstart.isot, dt.sec), waterfall) if do_foldspec: foldspec = np.zeros_like(myfoldspec) if comm.rank == 0 else None print("Rank {0} is entering comm.Reduce".format(comm.rank)) comm.Reduce(myfoldspec, foldspec, op=MPI.SUM, root=0) del myfoldspec # save memory on node 0 icount = np.zeros_like(myicount) if comm.rank == 0 else None comm.Reduce(myicount, icount, op=MPI.SUM, root=0) del myicount # save memory on node 0 if comm.rank == 0: fname = ("{0}foldspec_{1}+{2:08}sec.npy") np.save(fname.format(savepref, tstart.isot, dt.sec), foldspec) iname = ("{0}icount_{1}+{2:08}sec.npy") np.save(iname.format(savepref, tstart.isot, dt.sec), icount) if comm.rank == 0: if do_foldspec and foldspec.ndim == 3: # sum over time slices -> pulse profile vs channel foldspec1 = normalize_counts(foldspec.sum(0).astype(np.float64), icount.sum(0).astype(np.int64)) # sum over channels -> pulse profile vs time foldspec3 = normalize_counts(foldspec.sum(1).astype(np.float64), icount.sum(1).astype(np.int64)) fluxes = foldspec1.sum(axis=0) with open('{0}flux_{1}+{2:08}sec.dat' .format(savepref, tstart.isot, dt.sec), 'w') as f: for i, flux in enumerate(fluxes): f.write('{0:12d} {1:12.9g}\n'.format(i+1, flux)) # ratio'd flux only if file will not be ridiculously large if ntbin*ngate < 10000: foldspec2 = normalize_counts(foldspec, icount) plots = True if plots and do_waterfall and waterfall.ndim == 2: # no polarizations w = waterfall.copy() pmap('{0}waterfall_{1}+{2:08}sec.pgm' .format(savepref, tstart.isot, dt.sec), w, 1, verbose=True) if plots and do_foldspec and foldspec.ndim == 3: pmap('{0}folded_{1}+{2:08}sec.pgm' .format(savepref, tstart.isot, dt.sec), foldspec1, 0, verbose) pmap('{0}folded3_{1}+{2:08}sec.pgm' .format(savepref, tstart.isot, dt.sec), foldspec3.T, 0, verbose) # ratio'd flux only if file will not be ridiculously large if ntbin*ngate < 10000: pmap('{0}foldedbin_{1}+{2:08}sec.pgm' .format(savepref, tstart.isot, dt.sec), foldspec2.transpose(1,2,0).reshape(nchan,-1), 1, verbose)
np.mod(gmststart, 24.), np.mod(gmststop, 24.))) # get corresponding orbital phases for a range of dates #ist_date1 = '2013-06-16 12:00:00' #ist_date2 = '2013-07-03 12:00:00' ist_date1 = '2013-07-24 12:00:00' ist_date2 = '2013-08-08 12:00:00' ist_utc = 5.5 / 24. mjd1 = Time(ist_date1, scale='utc').mjd - ist_utc mjd2 = Time(ist_date2, scale='utc').mjd - ist_utc for mjd in np.arange(mjd1, mjd2 + 1.e-5): time = Time(mjd, format='mjd', scale='utc', precision=0) ut_start = gmst2time(gmststart, time) ut_stop = gmst2time(gmststop, time) ph_start, ph_stop = src.phase(ut_start), src.phase(ut_stop) ist_start = ut_start + TimeDelta(ist_utc, format='jd') ist_stop = ut_stop + TimeDelta(ist_utc, format='jd') print('{}-{}: {:4.2f}-{:4.2f}'.format(ist_start.iso, ist_stop.iso[11:], ph_start, ph_stop)) # 0834+06 before 1957+20 # # 1133+16 before J1012+5207 # # # Need scintellation data for B1957, J1012 # # LOFAR how high makes it useful? (elevation > 30?)
# possible offset nhead = recsize * 1000 ntbin = 10 # number of bins the time series is split into for folding ntw = min(100000, nt * ntint) # number of samples to combine for waterfall samplerate = 200 * u.MHz # account for offset, recalling there are 2 samples per byte phasepol.window += (nhead * 2 / samplerate).to(u.second).value fedge = 200. * u.MHz fedge_at_top = True fref = 150. * u.MHz # ref. freq. for dispersion measure time0 = Time(date_dict[psr], scale='utc') + TimeDelta(4 * 3600, format='sec') verbose = 'very' do_waterfall = True do_foldspec = True dedisperse = 'by-channel' #with open(file1, 'rb') as fh1: with multifile(seq_file, raw_files) as fh1: foldspec2, waterfall = fold(fh1, '4bit', samplerate, fedge, fedge_at_top, nchan,
############################################################################## # The data from the TimeSeries can be retrieved in a number of formats: ts_goes.to_dataframe() ts_goes.to_table() ts_goes.to_array() # Note: the array doesn't include the datetime index column. ############################################################################## # Creating a TimeSeries from scratch can be done in a lot of ways, much like a # Map. # Input data can be in the form of a Pandas DataFrame (preferred), an astropy # Table or a Numpy Array. # To generate some data and the corresponding dates base = datetime.datetime.today() dates = base - TimeDelta(np.arange(24 * 60) * u.minute) intensity = np.sin(np.arange(0, 12 * np.pi, ((12 * np.pi) / (24 * 60)))) # Create the data DataFrame, header MetaDict and units OrderedDict data = DataFrame(intensity, index=dates, columns=['intensity']) units = OrderedDict([('intensity', u.W / u.m**2)]) meta = MetaDict({'key': 'value'}) # Create the time series ts_custom = sunpy.timeseries.TimeSeries(data, meta, units) # A more manual dataset would be a numpy array, which we can creat using: tm = Time(['2000:002', '2001:345', '2002:345']) a = [1, 4, 5] b = [2.0, 5.0, 8.2] c = ['x', 'y', 'z'] arr = np.stack([tm, a, b, c], axis=1) # Note: this array needs to have the times in the first column, this can be in
def read_iris_spectrograph_level2_fits(filenames, spectral_windows=None, uncertainty=True, memmap=False): """ Reads IRIS level 2 spectrograph FITS from an OBS into an IRISSpectrograph instance. Parameters ---------- filenames: `list` of `str` or `str` Filename of filenames to be read. They must all be associated with the same OBS number. spectral_windows: iterable of `str` or `str` Spectral windows to extract from files. Default=None, implies, extract all spectral windows. Returns ------- result: `irispy.spectrograph.IRISSpectrograph` """ if type(filenames) is str: filenames = [filenames] for f, filename in enumerate(filenames): hdulist = fits.open(filename, memmap=memmap, do_not_scale_image_data=memmap) hdulist.verify('fix') if f == 0: # Determine number of raster positions in a scan raster_positions_per_scan = int(hdulist[0].header["NRASTERP"]) # Collecting the window observations. windows_in_obs = np.array([ hdulist[0].header["TDESC{0}".format(i)] for i in range(1, hdulist[0].header["NWIN"] + 1) ]) # If spectral_window is not set then get every window. # Else take the appropriate windows if not spectral_windows: spectral_windows_req = windows_in_obs window_fits_indices = range(1, len(hdulist) - 2) else: if type(spectral_windows) is str: spectral_windows_req = [spectral_windows] else: spectral_windows_req = spectral_windows spectral_windows_req = np.asarray(spectral_windows_req, dtype="U") window_is_in_obs = np.asarray([ window in windows_in_obs for window in spectral_windows_req ]) if not all(window_is_in_obs): missing_windows = window_is_in_obs == False raise ValueError( "Spectral windows {0} not in file {1}".format( spectral_windows[missing_windows], filenames[0])) window_fits_indices = np.nonzero( np.in1d(windows_in_obs, spectral_windows))[0] + 1 # Generate top level meta dictionary from first file # main header. top_meta = { "TELESCOP": hdulist[0].header["TELESCOP"], "INSTRUME": hdulist[0].header["INSTRUME"], "DATA_LEV": hdulist[0].header["DATA_LEV"], "OBSID": hdulist[0].header["OBSID"], "OBS_DESC": hdulist[0].header["OBS_DESC"], "STARTOBS": Time(hdulist[0].header["STARTOBS"]), "ENDOBS": Time(hdulist[0].header["ENDOBS"]), "SAT_ROT": hdulist[0].header["SAT_ROT"] * u.deg, "AECNOBS": int(hdulist[0].header["AECNOBS"]), "FOVX": hdulist[0].header["FOVX"] * u.arcsec, "FOVY": hdulist[0].header["FOVY"] * u.arcsec, "SUMSPTRN": hdulist[0].header["SUMSPTRN"], "SUMSPTRF": hdulist[0].header["SUMSPTRF"], "SUMSPAT": hdulist[0].header["SUMSPAT"], "NEXPOBS": hdulist[0].header["NEXPOBS"], "NRASTERP": hdulist[0].header["NRASTERP"], "KEYWDDOC": hdulist[0].header["KEYWDDOC"] } # Initialize meta dictionary for each spectral_window window_metas = {} for i, window_name in enumerate(spectral_windows_req): if "FUV" in hdulist[0].header["TDET{0}".format( window_fits_indices[i])]: spectral_summing = hdulist[0].header["SUMSPTRF"] else: spectral_summing = hdulist[0].header["SUMSPTRN"] window_metas[window_name] = { "detector type": hdulist[0].header["TDET{0}".format( window_fits_indices[i])], "spectral window": hdulist[0].header["TDESC{0}".format( window_fits_indices[i])], "brightest wavelength": hdulist[0].header["TWAVE{0}".format( window_fits_indices[i])], "min wavelength": hdulist[0].header["TWMIN{0}".format( window_fits_indices[i])], "max wavelength": hdulist[0].header["TWMAX{0}".format( window_fits_indices[i])], "SAT_ROT": hdulist[0].header["SAT_ROT"], "spatial summing": hdulist[0].header["SUMSPAT"], "spectral summing": spectral_summing } # Create a empty list for every spectral window and each # spectral window is a key for the dictionary. data_dict = dict([(window_name, list()) for window_name in spectral_windows_req]) # Determine extra coords for this raster. times = (Time(hdulist[0].header["STARTOBS"]) + TimeDelta( hdulist[-2].data[:, hdulist[-2].header["TIME"]], format='sec')) raster_positions = np.arange(int(hdulist[0].header["NRASTERP"])) pztx = hdulist[-2].data[:, hdulist[-2].header["PZTX"]] * u.arcsec pzty = hdulist[-2].data[:, hdulist[-2].header["PZTY"]] * u.arcsec xcenix = hdulist[-2].data[:, hdulist[-2].header["XCENIX"]] * u.arcsec ycenix = hdulist[-2].data[:, hdulist[-2].header["YCENIX"]] * u.arcsec obs_vrix = hdulist[-2].data[:, hdulist[-2].header["OBS_VRIX"]] * u.m / u.s ophaseix = hdulist[-2].data[:, hdulist[-2].header["OPHASEIX"]] exposure_times_fuv = hdulist[-2].data[:, hdulist[-2]. header["EXPTIMEF"]] * u.s exposure_times_nuv = hdulist[-2].data[:, hdulist[-2]. header["EXPTIMEN"]] * u.s # If OBS is raster, include raster positions. Otherwise don't. if top_meta["NRASTERP"] > 1: general_extra_coords = [("time", 0, times), ("raster position", 0, np.arange(top_meta["NRASTERP"])), ("pztx", 0, pztx), ("pzty", 0, pzty), ("xcenix", 0, xcenix), ("ycenix", 0, ycenix), ("obs_vrix", 0, obs_vrix), ("ophaseix", 0, ophaseix)] else: general_extra_coords = [("time", 0, times), ("pztx", 0, pztx), ("pzty", 0, pzty), ("xcenix", 0, xcenix), ("ycenix", 0, ycenix), ("obs_vrix", 0, obs_vrix), ("ophaseix", 0, ophaseix)] for i, window_name in enumerate(spectral_windows_req): # Determine values of properties dependent on detector type. if "FUV" in hdulist[0].header["TDET{0}".format( window_fits_indices[i])]: exposure_times = exposure_times_fuv DN_unit = iris_tools.DN_UNIT["FUV"] readout_noise = iris_tools.READOUT_NOISE["FUV"] elif "NUV" in hdulist[0].header["TDET{0}".format( window_fits_indices[i])]: exposure_times = exposure_times_nuv DN_unit = iris_tools.DN_UNIT["NUV"] readout_noise = iris_tools.READOUT_NOISE["NUV"] else: raise ValueError( "Detector type in FITS header not recognized.") # Derive WCS, data and mask for NDCube from file. # Sit-and-stare have a CDELT of 0 which causes issues in astropy WCS. # In this case, set CDELT to a tiny non-zero number. if hdulist[window_fits_indices[i]].header["CDELT3"] == 0: hdulist[window_fits_indices[i]].header["CDELT3"] = 1e-10 wcs_ = WCS(hdulist[window_fits_indices[i]].header) if not memmap: data_mask = hdulist[window_fits_indices[i]].data == -200. else: data_mask = None # Derive extra coords for this spectral window. window_extra_coords = copy.deepcopy(general_extra_coords) window_extra_coords.append(("exposure time", 0, exposure_times)) # Collect metadata relevant to single files. try: date_obs = Time(hdulist[0].header["DATE_OBS"]) except ValueError: date_obs = None try: date_end = Time(hdulist[0].header["DATE_END"]) except ValueError: date_end = None single_file_meta = { "SAT_ROT": hdulist[0].header["SAT_ROT"] * u.deg, "DATE_OBS": date_obs, "DATE_END": date_end, "HLZ": bool(int(hdulist[0].header["HLZ"])), "SAA": bool(int(hdulist[0].header["SAA"])), "DSUN_OBS": hdulist[0].header["DSUN_OBS"] * u.m, "IAECEVFL": hdulist[0].header["IAECEVFL"], "IAECFLAG": hdulist[0].header["IAECFLAG"], "IAECFLFL": hdulist[0].header["IAECFLFL"], "KEYWDDOC": hdulist[0].header["KEYWDDOC"], "detector type": hdulist[0].header["TDET{0}".format(window_fits_indices[i])], "spectral window": window_name, "OBSID": hdulist[0].header["OBSID"], "OBS_DESC": hdulist[0].header["OBS_DESC"], "STARTOBS": Time(hdulist[0].header["STARTOBS"]), "ENDOBS": Time(hdulist[0].header["ENDOBS"]) } # Derive uncertainty of data if uncertainty: out_uncertainty = u.Quantity( np.sqrt((hdulist[window_fits_indices[i]].data * DN_unit).to(u.photon).value + readout_noise.to(u.photon).value**2), unit=u.photon).to(DN_unit).value else: out_uncertainty = None # Appending NDCube instance to the corresponding window key in dictionary's list. data_dict[window_name].append( IRISSpectrogramCube(hdulist[window_fits_indices[i]].data, wcs_, out_uncertainty, DN_unit, single_file_meta, window_extra_coords, mask=data_mask)) hdulist.close() # Construct dictionary of IRISSpectrogramCubeSequences for spectral windows data = dict([(window_name, IRISSpectrogramCubeSequence(data_dict[window_name], window_metas[window_name], common_axis=0)) for window_name in spectral_windows_req]) # Initialize an IRISSpectrograph object. return IRISSpectrograph(data, meta=top_meta)
"%Y-%b-%d", # Example 2007-May-04 "%Y-%m-%d", # Example 2007-05-04 "%Y/%m/%d", # Example 2007/05/04 "%d-%b-%Y", # Example 04-May-2007 "%d-%b-%Y %H:%M:%S.%f", # Example 04-May-2007 21:08:12.999999 "%Y%m%d_%H%M%S", # Example 20070504_210812 "%Y:%j:%H:%M:%S", # Example 2012:124:21:08:12 "%Y:%j:%H:%M:%S.%f", # Example 2012:124:21:08:12.999999 "%Y%m%d%H%M%S", # Example 20140101000001 (JSOC/VSO Export/Downloads) "%Y.%m.%d_%H:%M:%S_TAI", # Example 2016.05.04_21:08:12_TAI - JSOC "%Y.%m.%d_%H:%M:%S_UTC", # Example 2016.05.04_21:08:12_UTC - JSOC "%Y.%m.%d_%H:%M:%S", # Example 2016.05.04_21:08:12 - JSOC "%Y/%m/%dT%H:%M", # Example 2007/05/04T21:08 ] _ONE_DAY_TIMEDELTA = TimeDelta(1 * u.day) def is_time_equal(t1, t2): """ Work around for https://github.com/astropy/astropy/issues/6970. Remove the usage of this function once the fix is in place. """ if abs(t1 - t2) < 1 * u.nanosecond: return True return False def _group_or_none(match, group, fun): try:
def test_absolute_times(data, timedelta): # Make sure that we handle absolute times correctly. We also check that # TimeDelta works properly when timedelta is True. # The example data uses relative times t, y, dy, params = data # FIXME: There seems to be a numerical stability issue in that if we run # the algorithm with the same values but offset in time, the transit_time # is not offset by a fixed amount. To avoid this issue in this test, we # make sure the first time is also the smallest so that internally the # values of the relative time should be the same. t[0] = 0. # Add units t = t * u.day y = y * u.mag dy = dy * u.mag # We now construct a set of absolute times but keeping the rest the same. start = Time('2019-05-04T12:34:56') trel = TimeDelta(t) if timedelta else t t = trel + start # and we set up two instances of BoxLeastSquares, one with absolute and one # with relative times. bls1 = BoxLeastSquares(t, y, dy) bls2 = BoxLeastSquares(trel, y, dy) results1 = bls1.autopower(0.16 * u.day) results2 = bls2.autopower(0.16 * u.day) # All the results should match except transit time which should be # absolute instead of relative in the first case. for key in results1: if key == 'transit_time': assert_quantity_allclose((results1[key] - start).to(u.day), results2[key]) elif key == 'objective': assert results1[key] == results2[key] else: assert_allclose(results1[key], results2[key]) # Check that model evaluation works fine model1 = bls1.model(t, 0.2 * u.day, 0.05 * u.day, Time('2019-06-04T12:34:56')) model2 = bls2.model(trel, 0.2 * u.day, 0.05 * u.day, TimeDelta(1 * u.day)) assert_quantity_allclose(model1, model2) # Check model validation with pytest.raises(TypeError) as exc: bls1.model(t, 0.2 * u.day, 0.05 * u.day, 1 * u.day) assert exc.value.args[0] == ('transit_time was provided as a relative time ' 'but the BoxLeastSquares class was initialized ' 'with absolute times.') with pytest.raises(TypeError) as exc: bls1.model(trel, 0.2 * u.day, 0.05 * u.day, Time('2019-06-04T12:34:56')) assert exc.value.args[0] == ('t_model was provided as a relative time ' 'but the BoxLeastSquares class was initialized ' 'with absolute times.') with pytest.raises(TypeError) as exc: bls2.model(trel, 0.2 * u.day, 0.05 * u.day, Time('2019-06-04T12:34:56')) assert exc.value.args[0] == ('transit_time was provided as an absolute time ' 'but the BoxLeastSquares class was initialized ' 'with relative times.') with pytest.raises(TypeError) as exc: bls2.model(t, 0.2 * u.day, 0.05 * u.day, 1 * u.day) assert exc.value.args[0] == ('t_model was provided as an absolute time ' 'but the BoxLeastSquares class was initialized ' 'with relative times.') # Check compute_stats stats1 = bls1.compute_stats(0.2 * u.day, 0.05 * u.day, Time('2019-06-04T12:34:56')) stats2 = bls2.compute_stats(0.2 * u.day, 0.05 * u.day, 1 * u.day) for key in stats1: if key == 'transit_times': assert_quantity_allclose((stats1[key] - start).to(u.day), stats2[key], atol=1e-10 * u.day) elif key.startswith('depth'): for value1, value2 in zip(stats1[key], stats2[key]): assert_quantity_allclose(value1, value2) else: assert_allclose(stats1[key], stats2[key]) # Check compute_stats validation with pytest.raises(TypeError) as exc: bls1.compute_stats(0.2 * u.day, 0.05 * u.day, 1 * u.day) assert exc.value.args[0] == ('transit_time was provided as a relative time ' 'but the BoxLeastSquares class was initialized ' 'with absolute times.') with pytest.raises(TypeError) as exc: bls2.compute_stats(0.2 * u.day, 0.05 * u.day, Time('2019-06-04T12:34:56')) assert exc.value.args[0] == ('transit_time was provided as an absolute time ' 'but the BoxLeastSquares class was initialized ' 'with relative times.') # Check transit_mask mask1 = bls1.transit_mask(t, 0.2 * u.day, 0.05 * u.day, Time('2019-06-04T12:34:56')) mask2 = bls2.transit_mask(trel, 0.2 * u.day, 0.05 * u.day, 1 * u.day) assert_equal(mask1, mask2) # Check transit_mask validation with pytest.raises(TypeError) as exc: bls1.transit_mask(t, 0.2 * u.day, 0.05 * u.day, 1 * u.day) assert exc.value.args[0] == ('transit_time was provided as a relative time ' 'but the BoxLeastSquares class was initialized ' 'with absolute times.') with pytest.raises(TypeError) as exc: bls1.transit_mask(trel, 0.2 * u.day, 0.05 * u.day, Time('2019-06-04T12:34:56')) assert exc.value.args[0] == ('t was provided as a relative time ' 'but the BoxLeastSquares class was initialized ' 'with absolute times.') with pytest.raises(TypeError) as exc: bls2.transit_mask(trel, 0.2 * u.day, 0.05 * u.day, Time('2019-06-04T12:34:56')) assert exc.value.args[0] == ('transit_time was provided as an absolute time ' 'but the BoxLeastSquares class was initialized ' 'with relative times.') with pytest.raises(TypeError) as exc: bls2.transit_mask(t, 0.2 * u.day, 0.05 * u.day, 1 * u.day) assert exc.value.args[0] == ('t was provided as an absolute time ' 'but the BoxLeastSquares class was initialized ' 'with relative times.')
def track(self, target_or_ra, dec=None, duration=0, start_time=None, verbose=True): """ Given a target name and a tracking duration in seconds, start tracking the source. If the 'dec' keyword is not None, the target is intepreted to be a RA. If the duration is less than or equal to zero the default of 12 hours is used. .. note:: The tracking can be canceled at any time with a control-C. """ # Force to string target_or_ra = str(target_or_ra) if dec is not None: dec = str(dec) # Load in where we are obs = EarthLocation.from_geocentric( *self.control_instance.station.ecef, unit=u.m) # Resolve the name into coordinates if target_or_ra.lower() in solar_system_ephemeris.bodies: if target_or_ra.lower().startswith('earth'): raise ValueError(f"Invalid target: '{target_or_ra}'") sc = get_body(target_or_ra.lower(), Time.now(), location=obs) if verbose: print(f"Resolved '{target_or_ra}' to {target_or_ra.lower()}") else: if dec is not None: ra = Angle(target_or_ra, unit='hourangle') dec = Angle(dec, unit='deg') sc = SkyCoord(ra, dec, frame='fk5') if verbose: print( f"Resolved '{target_or_ra}, {dec}' to RA {sc.ra}, Dec. {sc.dec}" ) else: sc = SkyCoord.from_name(target_or_ra) if verbose: print( f"Resolved '{target_or_ra}' to RA {sc.ra}, Dec. {sc.dec}" ) # Figure out the duration of the tracking if duration <= 0: duration = 86400.0 / 2 # Set the pointing update time offset - this is half the update interval # so that we should end up with a nice scalloped pattern puto = TimeDelta(min([duration, self.update_interval]) / 2.0, format='sec') # Set the tracking stop time if start_time is None: start_time = time.time() t_stop = start_time + duration try: # Go! t = time.time() while t < t_stop: ## Get a time marker so that we can account for how long the ## update takes t_mark = time.time() ## Figure out where the target will be in puto seconds aa = sc.transform_to( AltAz(obstime=Time.now() + puto, location=obs)) az = aa.az.deg alt = aa.alt.deg if verbose: print( f"At {time.time():.1f}, moving to azimuth {aa.az}, altitude {aa.alt}" ) ## Point self.control_instance.set_beam_pointing(az, alt, degrees=True, load_time=t_mark + 2) ## Find how much time we used and when we should sleep until t_used = time.time() - t_mark t_sleep_until = t + self.update_interval - t_used ## Sleep to wait it out in increments of 0.01 s so that a control-C ## doesn't take forever to register while t < t_sleep_until and t < t_stop: time.sleep(0.01) t = time.time() except KeyboardInterrupt: # We gave up, end it now pass
############################################################################## # The data from the TimeSeries can be retrieved in a number of formats: ts_goes.to_dataframe() ts_goes.to_table() ts_goes.to_array() ############################################################################## # Creating a TimeSeries from scratch can be done in a lot of ways, much like a # Map. # Input data can be in the form of a Pandas DataFrame (preferred), an astropy # table or a numpy array. # To generate some data and the corresponding dates base = datetime.datetime.today() dates = Time(base) - TimeDelta(np.arange(24 * 60)*u.minute) intensity = np.sin(np.arange(0, 12 * np.pi, ((12 * np.pi) / (24 * 60)))) # Create the data DataFrame, header MetaDict and units OrderedDict data = DataFrame(intensity, index=dates, columns=['intensity']) units = OrderedDict([('intensity', u.W / u.m**2)]) meta = MetaDict({'key': 'value'}) # Create the time series ts_custom = sunpy.timeseries.TimeSeries(data, meta, units) # A more manual dataset would be a numpy array, which we can creat using: tm = Time(['2000:002', '2001:345', '2002:345']) a = [1, 4, 5] b = [2.0, 5.0, 8.2] c = ['x', 'y', 'z'] arr = np.stack([tm, a, b, c], axis=1) # Note: this array needs to have the times in the first column, this can be in
def get_start_time(ra0_deg, length_sec): """Returns optimal start time for field RA and observation length.""" t = Time('2000-01-01 00:00:00', scale='utc', location=('116.764d', '0d')) dt_hours = 24.0 - t.sidereal_time('apparent').hour + (ra0_deg / 15.0) start = t + TimeDelta(dt_hours * 3600.0 - length_sec / 2.0, format='sec') return start.value
def whenup(date=None,verbose=False): ''' Find out the times when preferred sources are up for a given date. Prints the result of source rise and set times for preferred sources: Sun, 0319+415, 1229+020, 1331+305, 2136+006, 2253+161 Optional arguments: date: Time() object giving start date (time of day is ignored) or None for current date. verbose: If True, actually print the table of times to the screen Returns: dictionary of time objects with keys 'taz', 'teq', 'tgap', each being a two-element Time() object, where first time is start (rise) and second is end (set), and 'lines', which is a printable table of times. ''' srclist = ['Sun ', '0319+415', '1229+020', '1331+305', '2136+006', '2253+161'] # Use the 24-h day specified by date (i.e. drop the time of day) if date is None: # Use today's date mjd = int(Time.now().mjd) else: mjd = int(date.mjd) t = Time(mjd,format='mjd') # Add times in 1-min steps up to duration dur (hours) ts = t + TimeDelta(np.arange(0.,24.,1./60.)/24.,format='jd') aa = eovsa_cat.eovsa_array_with_cat() nt = len(ts) ra = np.zeros((len(srclist),nt)) ha = np.zeros((len(srclist),nt)) dec = np.zeros((len(srclist),nt)) alt = np.zeros((len(srclist),nt)) az = np.zeros((len(srclist),nt)) taz = [] teq = [] tgap = [] lines = [] for i in range(nt): aa.set_jultime(ts[i].jd) lst = aa.sidereal_time() for j,srcname in enumerate(srclist): src = aa.cat[srcname.split()[0]] src.compute(aa) ra[j,i] = src.ra ha[j,i] = lst - src.ra dec[j,i] = src.dec alt[j,i] = src.alt az[j,i] = src.az ra_deg = deg(ra) ha_deg = deg(ha) dec_deg = deg(dec) alt = deg(alt) az_deg = deg2(az) lines.append('Source Alt-Az Equatorial Gap') lines.append(' Name Rise Set Rise Set Start End') lines.append('-------- ----- ----- ----- ----- ----- -----') for j in range(len(srclist)): iset_eq = np.where(np.abs(ha_deg[j] - 55.0) < 0.15)[0][0] irise_eq = np.where(np.abs(ha_deg[j] + 55.0) < 0.15)[0][0] trise_eq = ts[irise_eq] tset_eq = ts[iset_eq] if iset_eq < irise_eq: if j == 0: tset_eq += TimeDelta(1,format='jd') else: tset_eq += TimeDelta(1436./60./24.,format='jd') for iwindow in np.arange(0.1,0.2,0.01): try: i1 = np.where(np.abs(alt[j] - 10.0) < iwindow)[0][0] i2 = np.where(np.abs(alt[j] - 10.0) < iwindow)[0][1] if i2 == i1+1: i2 = np.where(np.abs(alt[j] - 10.0) < iwindow)[0][2] break except: print 'Window',iwindow,'did not work. Trying again' if alt[j,i1] < alt[j,i1+1]: irise_az = i1 iset_az = i2 else: irise_az = i2 iset_az = i1 trise_az = ts[irise_az] tset_az = ts[iset_az] if iset_az < irise_az: if j == 0: tset_az += TimeDelta(1,format='jd') else: tset_az += TimeDelta(1436./60./24.,format='jd') if j == 1: up, = np.where(alt[j] > 10.) j1 = np.where(np.abs(az_deg[j,up] - 35.0) < 1.0)[0][0] j2 = np.where(np.abs(az_deg[j,up] - 325.0) < 1.0)[0][0] jset = up[j1] jrise = up[j2] tset_gap = ts[jset] trise_gap = ts[jrise] if jrise < jset: trise_gap += TimeDelta(1436./60./24.,format='jd') taz.append(Time([trise_az.iso,tset_az.iso])) teq.append(Time([trise_eq.iso,tset_eq.iso])) tgap.append(Time([tset_gap.iso,trise_gap.iso])) lines.append('{0} {1} {2} {3} {4} {5} {6}'.format(srclist[j], trise_az.iso[11:16], tset_az.iso[11:16], trise_eq.iso[11:16], tset_eq.iso[11:16], tset_gap.iso[11:16], trise_gap.iso[11:16])) else: taz.append(Time([trise_az.iso,tset_az.iso])) teq.append(Time([trise_eq.iso,tset_eq.iso])) tgap.append((None,None)) lines.append('{0} {1} {2} {3} {4} {5} {6}'.format(srclist[j], trise_az.iso[11:16], tset_az.iso[11:16], trise_eq.iso[11:16], tset_eq.iso[11:16], ' --- ',' --- ')) if verbose: for line in lines: print line return {'source':srclist,'taz':taz, 'teq':teq, 'tgap':tgap, 'lines':lines}
def write_event_file(events, parameters, filename, overwrite=False): from astropy.time import Time, TimeDelta mylog.info("Writing events to file %s." % filename) t_begin = Time.now() dt = TimeDelta(parameters["exposure_time"], format='sec') t_end = t_begin + dt col_x = pyfits.Column(name='X', format='D', unit='pixel', array=events["xpix"]) col_y = pyfits.Column(name='Y', format='D', unit='pixel', array=events["ypix"]) col_e = pyfits.Column(name='ENERGY', format='E', unit='eV', array=events["energy"] * 1000.) col_dx = pyfits.Column(name='DETX', format='D', unit='pixel', array=events["detx"]) col_dy = pyfits.Column(name='DETY', format='D', unit='pixel', array=events["dety"]) col_id = pyfits.Column(name='CCD_ID', format='D', unit='pixel', array=events["ccd_id"]) chantype = parameters["channel_type"] if chantype == "PHA": cunit = "adu" elif chantype == "PI": cunit = "Chan" col_ch = pyfits.Column(name=chantype.upper(), format='1J', unit=cunit, array=events[chantype]) col_t = pyfits.Column(name="TIME", format='1D', unit='s', array=events['time']) cols = [col_e, col_x, col_y, col_ch, col_t, col_dx, col_dy, col_id] coldefs = pyfits.ColDefs(cols) tbhdu = pyfits.BinTableHDU.from_columns(coldefs) tbhdu.name = "EVENTS" tbhdu.header["MTYPE1"] = "sky" tbhdu.header["MFORM1"] = "x,y" tbhdu.header["MTYPE2"] = "EQPOS" tbhdu.header["MFORM2"] = "RA,DEC" tbhdu.header["TCTYP2"] = "RA---TAN" tbhdu.header["TCTYP3"] = "DEC--TAN" tbhdu.header["TCRVL2"] = parameters["sky_center"][0] tbhdu.header["TCRVL3"] = parameters["sky_center"][1] tbhdu.header["TCDLT2"] = -parameters["plate_scale"] tbhdu.header["TCDLT3"] = parameters["plate_scale"] tbhdu.header["TCRPX2"] = parameters["pix_center"][0] tbhdu.header["TCRPX3"] = parameters["pix_center"][1] tbhdu.header["TCUNI2"] = "deg" tbhdu.header["TCUNI3"] = "deg" tbhdu.header["TLMIN2"] = 0.5 tbhdu.header["TLMIN3"] = 0.5 tbhdu.header["TLMAX2"] = 2.0 * parameters["num_pixels"] + 0.5 tbhdu.header["TLMAX3"] = 2.0 * parameters["num_pixels"] + 0.5 tbhdu.header["TLMIN4"] = parameters["chan_lim"][0] tbhdu.header["TLMAX4"] = parameters["chan_lim"][1] tbhdu.header["TLMIN6"] = -0.5 * parameters["num_pixels"] tbhdu.header["TLMAX6"] = 0.5 * parameters["num_pixels"] tbhdu.header["TLMIN7"] = -0.5 * parameters["num_pixels"] tbhdu.header["TLMAX7"] = 0.5 * parameters["num_pixels"] tbhdu.header["EXPOSURE"] = parameters["exposure_time"] tbhdu.header["TSTART"] = 0.0 tbhdu.header["TSTOP"] = parameters["exposure_time"] tbhdu.header["HDUVERS"] = "1.1.0" tbhdu.header["RADECSYS"] = "FK5" tbhdu.header["EQUINOX"] = 2000.0 tbhdu.header["HDUCLASS"] = "OGIP" tbhdu.header["HDUCLAS1"] = "EVENTS" tbhdu.header["HDUCLAS2"] = "ACCEPTED" tbhdu.header["DATE"] = t_begin.tt.isot tbhdu.header["DATE-OBS"] = t_begin.tt.isot tbhdu.header["DATE-END"] = t_end.tt.isot tbhdu.header["RESPFILE"] = os.path.split(parameters["rmf"])[-1] tbhdu.header["PHA_BINS"] = parameters["nchan"] tbhdu.header["ANCRFILE"] = os.path.split(parameters["arf"])[-1] tbhdu.header["CHANTYPE"] = parameters["channel_type"] tbhdu.header["MISSION"] = parameters["mission"] tbhdu.header["TELESCOP"] = parameters["telescope"] tbhdu.header["INSTRUME"] = parameters["instrument"] tbhdu.header["RA_PNT"] = parameters["sky_center"][0] tbhdu.header["DEC_PNT"] = parameters["sky_center"][1] tbhdu.header["ROLL_PNT"] = parameters["roll_angle"] tbhdu.header["AIMPT_X"] = parameters["aimpt_coords"][0] tbhdu.header["AIMPT_Y"] = parameters["aimpt_coords"][1] if parameters["dither_params"]["dither_on"]: tbhdu.header["DITHXAMP"] = parameters["dither_params"]["x_amp"] tbhdu.header["DITHYAMP"] = parameters["dither_params"]["y_amp"] tbhdu.header["DITHXPER"] = parameters["dither_params"]["x_period"] tbhdu.header["DITHYPER"] = parameters["dither_params"]["y_period"] start = pyfits.Column(name='START', format='1D', unit='s', array=np.array([0.0])) stop = pyfits.Column(name='STOP', format='1D', unit='s', array=np.array([parameters["exposure_time"]])) tbhdu_gti = pyfits.BinTableHDU.from_columns([start, stop]) tbhdu_gti.name = "STDGTI" tbhdu_gti.header["TSTART"] = 0.0 tbhdu_gti.header["TSTOP"] = parameters["exposure_time"] tbhdu_gti.header["HDUCLASS"] = "OGIP" tbhdu_gti.header["HDUCLAS1"] = "GTI" tbhdu_gti.header["HDUCLAS2"] = "STANDARD" tbhdu_gti.header["RADECSYS"] = "FK5" tbhdu_gti.header["EQUINOX"] = 2000.0 tbhdu_gti.header["DATE"] = t_begin.tt.isot tbhdu_gti.header["DATE-OBS"] = t_begin.tt.isot tbhdu_gti.header["DATE-END"] = t_end.tt.isot hdulist = [pyfits.PrimaryHDU(), tbhdu, tbhdu_gti] pyfits.HDUList(hdulist).writeto(filename, overwrite=overwrite)
sd = SphericalCosLatDifferential([0, 1] * u.mas / u.yr, [0, 1] * u.mas / u.yr, 10 * u.km / u.s) srd = SphericalRepresentation(sr, differentials=sd) sc = SkyCoord([1, 2], [3, 4], unit='deg,deg', frame='fk4', obstime='J1990.5') scc = sc.copy() scc.representation_type = 'cartesian' tm = Time([2450814.5, 2450815.5], format='jd', scale='tai', location=el) # NOTE: in the test below the name of the column "x" for the Quantity is # important since it tests the fix for #10215 (namespace clash, where "x" # clashes with "el2.x"). mixin_cols = { 'tm': tm, 'dt': TimeDelta([1, 2] * u.day), 'sc': sc, 'scc': scc, 'scd': SkyCoord([1, 2], [3, 4], [5, 6], unit='deg,deg,m', frame='fk4', obstime=['J1990.5', 'J1991.5']), 'x': [1, 2] * u.m, 'lat': Latitude([1, 2] * u.deg), 'lon': Longitude([1, 2] * u.deg, wrap_angle=180. * u.deg), 'ang':
import astropy.units as u import astropy._erfa as erfa from astropy.time import Time, TimeDelta from astropy.time.utils import day_frac, two_sum from astropy.utils import iers allclose_jd = functools.partial(np.allclose, rtol=2.**-52, atol=0) allclose_jd2 = functools.partial(np.allclose, rtol=2.**-52, atol=2.**-52) # 20 ps atol allclose_sec = functools.partial(np.allclose, rtol=2.**-52, atol=2.**-52 * 24 * 3600) # 20 ps atol tiny = 2.**-52 dt_tiny = TimeDelta(tiny, format='jd') def test_abs_jd2_always_less_than_half(): """Make jd2 approach +/-0.5, and check that it doesn't go over.""" t1 = Time(2400000.5, [-tiny, +tiny], format='jd') assert np.all(t1.jd1 % 1 == 0) assert np.all(abs(t1.jd2) < 0.5) t2 = Time(2400000., [[0.5 - tiny, 0.5 + tiny], [-0.5 - tiny, -0.5 + tiny]], format='jd') assert np.all(t2.jd1 % 1 == 0) assert np.all(abs(t2.jd2) < 0.5) def test_addition(): """Check that an addition at the limit of precision (2^-52) is seen"""
def auto_open(cls, files=None): """Attempt to get an up-to-date leap-second list. The routine will try the files in sequence until it finds one whose expiration date is "good enough" (see below). If none are good enough, it returns the one with the most recent expiration date, warning if that file is expired. For remote files that are cached already, the cached file is tried first before attempting to retrieve it again. Parameters ---------- files : list of path-like, optional List of files/URLs to attempt to open. By default, uses ``cls._auto_open_files``. Returns ------- leap_seconds : `~astropy.utils.iers.LeapSeconds` Up to date leap-second table Notes ----- Bulletin C is released about 10 days after a possible leap second is introduced, i.e., mid-January or mid-July. Expiration days are thus generally at least 150 days after the present. We look for a file that expires more than 180 - `~astropy.utils.iers.Conf.auto_max_age` after the present. """ good_enough = cls._today() + TimeDelta( 180 - _none_to_float(conf.auto_max_age), format='jd') if files is None: # Basic files to go over (entries in _auto_open_files can be # configuration items, which we want to be sure are up to date). files = [getattr(conf, f, f) for f in cls._auto_open_files] # Remove empty entries. files = [f for f in files if f] # Our trials start with normal files and remote ones that are # already in cache. The bools here indicate that the cache # should be used. trials = [(f, True) for f in files if not urlparse(f).netloc or is_url_in_cache(f)] # If we are allowed to download, we try downloading new versions # if none of the above worked. if conf.auto_download: trials += [(f, False) for f in files if urlparse(f).netloc] self = None err_list = [] # Go through all entries, and return the first one that # is not expired, or the most up to date one. for f, allow_cache in trials: if not allow_cache: clear_download_cache(f) try: trial = cls.open(f, cache=True) except Exception as exc: err_list.append(exc) continue if self is None or trial.expires > self.expires: self = trial self.meta['data_url'] = str(f) if self.expires > good_enough: break if self is None: raise ValueError('none of the files could be read. The ' 'following errors were raised:\n' + str(err_list)) if self.expires < self._today(): warn('leap-second file is expired.', IERSStaleWarning) return self
def __init__(self, Max_Delta_days, planet=None): try: if planet == None: empty_class = True else: empty_class = False except Exception: if planet.all() == None: empty_class = True else: empty_class = False if empty_class: """ Create Empty class to load data from file """ self.name = None self.epoch = None self.tranmid_err = None self.period = None self.period_err = None self.transit_duration = None self.eccentricity = None self.star_Teff = None self.star_jmag = None self.pl_radj = None self.Planets_eclipse = None self.num_eclipses = None self.target_observable = [] self.eclipse_observable = [] else: """ Initialize Eclipse instance from Nasa query_planet object """ self.name = planet['pl_name'] self.epoch = Time(planet['pl_tranmid'], format='jd', scale='utc', location=paranal.location) if np.isnan(planet['pl_tranmiderr1']): self.tranmid_err = TimeDelta(0, format = 'jd') else: self.tranmid_err = TimeDelta(planet['pl_tranmiderr1']) # error into future self.period = planet['pl_orbper'] * u.day if np.isnan(planet['pl_orbpererr1']) or np.isnan(planet['pl_orbpererr2']): self.period_err = 0 * u.day else: if np.abs(planet['pl_orbpererr1']) > np.abs(planet['pl_orbpererr2']): self.period_err = planet['pl_orbpererr1'] * u.day else: self.period_err = planet['pl_orbpererr2'] * u.day self.transit_duration = planet['pl_trandur'] * u.hour #CAREFUL in nexa_old the pl_trandur is given in u.day self.eccentricity = planet['pl_orbeccen'] self.star_Teff = planet['st_teff'] self.star_jmag = planet['sy_jmag'] self.pl_radj = planet['pl_radj']*11.2 self.target_observable = [] self.eclipse_observable = [] """ Planet_next_eclipse : Class object with which the future transits of the planet can be calculated. For documentation review astroplan.EclipsingSystem documentation. WARNING: There are currently two major caveats in the implementation of ''EclipsingSystem''. The secondary eclipse time approximation is only accurate when the orbital eccentricity is small, and the eclipse times are computed without any barycentric corrections. The current implementation should only be used forapproximate mid-eclipse times for low eccentricity orbits, with event durations longer than the barycentric correction error (<=16 minutes). This is corrected for with the barycentric correction, which can be found in the classmethod Observability From EclipsingSystem.__doc__ """ Planet_next_eclipse = astroplan.EclipsingSystem( primary_eclipse_time=self.epoch, orbital_period=self.period, duration=self.transit_duration) self.Planets_eclipse = Planet_next_eclipse # time in barycentric frame # number of eclipses occurring during Max_Delta_days. self.num_eclipses = int(np.floor(Max_Delta_days / (self.period / u.day))) """ coordinates of the object in IRCS """ try: self.Coordinates = FixedTarget.from_name(self.name) except Exception: sky_coord = SkyCoord(ra = planet['ra']*u.deg, dec = planet['dec']*u.deg) self.Coordinates = FixedTarget(name=self.name, coord = sky_coord)
print("Specify either '--gps-start' or '--year-start', but not both") sys.exit(1) elif args.gpsstart is not None: try: starttime = Time(args.gpsstart, format='gps', scale='utc') except ValueError: Exception("Could not parse start GPS time: {}".format(args.gpsstart)) else: try: starttime = Time(args.yearstart, format='decimalyear', scale='utc') except ValueError: Exception("Could not parse start year: {}".format(args.yearstart)) # set the time step try: dt = TimeDelta(args.interval*3600., format='sec') except ValueError: Exception("Could not parse time interval: {}".format(args.interval)) # set the end time try: endtime = Time(starttime.decimalyear + args.nyears, format='decimalyear', scale='utc') + dt except ValueError: Exception("Could not parse total timespan") pos = [] vel = [] acc = [] # get positions, velocities and accelerations curtime = starttime
############################################################################## # Next let's show how to this looks like on the Sun. # Load in an AIA map: aia_map = sunpy.map.Map(sunpy.data.sample.AIA_171_IMAGE) ############################################################################## # Let's define our starting coordinates hpc_y = u.Quantity(np.arange(-700, 800, 100), u.arcsec) hpc_x = np.zeros_like(hpc_y) ############################################################################## # Let's define how many days in the future we want to rotate to dt = TimeDelta(4*u.day) future_date = aia_map.date + dt ############################################################################## # Now let's plot the original and rotated positions on the AIA map. fig = plt.figure() ax = plt.subplot(projection=aia_map) aia_map.plot() ax.set_title('The effect of {0} days of differential rotation'.format(dt.to(u.day).value)) aia_map.draw_grid() for this_hpc_x, this_hpc_y in zip(hpc_x, hpc_y): start_coord = SkyCoord(this_hpc_x, this_hpc_y, frame=aia_map.coordinate_frame) rotated_coord = solar_rotate_coordinate(start_coord, time=future_date) coord = SkyCoord([start_coord.Tx, rotated_coord.Tx],