def test_findnearest(): indf, xf = sd.find_nearest([10, 15, 12, 20, 14, 33], [32, 12.01]) assert_allclose(indf, [5, 2]) assert_allclose(xf, [33., 12.]) indf, xf = sd.find_nearest( (datetime.datetime(2012, 1, 1, 12), datetime.datetime(2012, 1, 1, 11)), datetime.datetime(2012, 1, 1, 11, 30)) assert_equal(indf, 0) assert_equal(xf, datetime.datetime(2012, 1, 1, 12))
def test_findnearest(): indf, xf = sd.find_nearest([10, 15, 12, 20, 14, 33], [32, 12.01]) assert (indf == [5, 2]).all() assert xf == approx([33.0, 12.0]) indf, xf = sd.find_nearest( (datetime.datetime(2012, 1, 1, 12), datetime.datetime(2012, 1, 1, 11)), datetime.datetime(2012, 1, 1, 11, 30), ) assert indf == 0 assert xf == datetime.datetime(2012, 1, 1, 12)
def optical(vidfn,calfn,treq,terror_cam): """ quick-n-dirty load of optical data to corroborate with other tle and ncdf data """ #data, rawFrameInd,finf = goRead(vidfn,xyPix=(512,512),xyBin=(1,1), ut1Req=T,kineticraw=1/fps,startUTC=tstart) treq -= timedelta(seconds=terror_cam) treq = forceutc(treq) treq = treq.timestamp() vidfn = Path(vidfn).expanduser() if not vidfn.suffix == '.h5': raise IOError('{} needs to be HST HDF5 file'.format(vidfn)) with h5py.File(str(vidfn),'r',libver='latest') as f: tcam = f['ut1_unix'] i = find_nearest(tcam,treq)[0] if i==0 or i==tcam.size-1: logging.critical('requested time {} at or past edge of camera time {}'.format(datetime.utcfromtimestamp(treq),datetime.utcfromtimestamp(tcam[i]))) tcam = f['ut1_unix'][i] img = f['rawimg'][i,...] llacam = f['sensorloc'].value #%% map pixels to sky calfn = Path(calfn).expanduser() with h5py.File(str(calfn),'r',libver='latest') as f: az = f['/az'].value el = f['/el'].value return img, tcam, llacam, az,el
def runglowaurora(params: dict, z_km: np.ndarray = None) -> xarray.Dataset: """ Runs Fortran GLOW program and collects results in friendly arrays with metadata. """ # %% (-2) check/process user inputs assert isinstance(params['flux'], (float, int, np.ndarray)) assert isinstance(params['E0'], (float, int)) assert isinstance(params['t0'], (datetime, str)) assert isinstance(params['glat'], (float, int)) assert isinstance(params['glon'], (float, int)) # %% (-1) if no manual f10.7 and ap, autoload by date if not 'f107a' in params or params['f107a'] is None: if getApF107 is None: raise ImportError(GRIDERR) f107Ap = getApF107(params['t0']) params['f107a'] = params['f107p'] = f107Ap['f107s'].item() params['f107'] = f107Ap['f107'].item() params['Ap'] = (f107Ap['Ap'].item(), ) * 7 # %% flux grid / date eflux = np.atleast_1d(params['flux']) yeardoy, utsec = datetime2yeardoy(params['t0'])[:2] # %% (0) define altitude grid [km] # FIXME: dynamic grid z_km = np.array( list(range(80, 110, 1)) + [110., 111.5, 113., 114.5] + list(range(116, 136, 2)) + [137., 140., 144., 148., 153., 158., 164., 170] + list( chain(range(176, 204, 7), range(205, 253, 8), range(254, 299, 9), range(300, 650, 10)))) if z_km is None: if glowalt is not None: z_km = glowalt() else: raise ImportError(GRIDERR) # %% (1) setup flux at top of ionosphere ener, dE = glowfort.egrid() if eflux.size == 1: logging.info( 'generating maxwellian input differential number flux spectrum') # maxwellian input PhiTop at top of ionosphere phitop = glowfort.maxt(eflux, params['E0'], ener, dE, itail=0, fmono=0, emono=0) elif eflux.size > 1: # eigenprofile generation, one non-zero bin at a time logging.info('running in eigenprofile mode') # FIXME should we interpolate instead? Maybe not, as long as we're consistent ref. Semeter 2006 e0ind = find_nearest(ener, params['e0'])[0] phitop = np.zeros_like(ener) phitop[e0ind] = ener[e0ind] # value in glow grid closest to zett grid else: return ValueError( 'I do not understand your electron flux input. Should be scalar or vector' ) phi = np.stack((ener, dE, phitop), 1) # Nalt x 3 assert phi.shape[1] == 3 # %% (2) msis,iri,glow model glowfort.glowbasic( yeardoy, utsec, params['glat'], params['glon'] % 360, params['f107a'], params['f107'], params['f107p'], params['Ap'], z_km, pyphi=phi, pyverbose=False, ) # %% (3) collect outputs lamb = [ 3371, 4278, 5200, 5577, 6300, 7320, 10400, 3466, 7774, 8446, 3726, 'LBH', 1356, 1493, 1304 ] # same for ZETA and ZCETA ions = [ 'nO+(2P)', 'nO+(2D)', 'nO+(4S)', 'nN+', 'nN2+', 'nO2+', 'nNO+', 'nO', 'nO2', 'nN2', 'nNO' ] neut = ['O', 'O2', 'N2'] sim = xarray.Dataset() # %% array of volume emission rates at each altitude; cm-3 s-1: sim['zeta'] = xarray.DataArray(glowfort.cglow.zeta.T, dims=['z_km', 'wavelength_nm'], coords={ 'z_km': z_km, 'wavelength_nm': lamb }) # %% array of contributions to each v.e.r at each alt; cm-3 s-1 Nalt x Nwavelength x Nprocess sim['zceta'] = xarray.DataArray( glowfort.cglow.zceta.T, # See Glow.txt. dims=['z_km', 'wavelength_nm', 'process'], coords={ 'z_km': z_km, 'wavelength_nm': lamb, 'process': range(glowfort.cglow.zceta.T.shape[2]) }) # %% electron impact ionization rates calculated by ETRANS; cm-3 s-1 sim['sion'] = xarray.DataArray(glowfort.cglow.sion.T, dims=['z_km', 'neutral_species'], coords={ 'z_km': z_km, 'neutral_species': neut }) # %% total photoionization rate at each altitude, cm-3 s-1 sim['tpi'] = xarray.DataArray(glowfort.cglow.tpi, dims=['z_km'], coords={'z_km': z_km}) # %% total electron impact ionization rate at each altitude, cm-3 s-1 sim['tei'] = xarray.DataArray(glowfort.cglow.tei, dims=['z_km'], coords={'z_km': z_km}) # %% PESPEC photoelectron production rate at energy, altitude; cm-3 s-1 sim['pespec'] = xarray.DataArray(glowfort.cglow.pespec.T, dims=['z_km', 'eV'], coords={ 'z_km': z_km, 'eV': ener }) # sim['photIon'] = xarray.DataArray(np.hstack((photI[:,None],ImpI[:,None],ecalc[:,None],ion)), # dims=['z_km','type'], # coords={'z_km':z_km, # 'type':['photoIoniz','eImpactIoniz','ne']+products}) # # sim['isr'] = xarray.DataArray(isr, # dims=['z_km','param'], # coords={'z_km':z_km,'param':['ne','Te','Ti']}) # # sim['phitop'] = xarray.DataArray(phi[:,2], # dims=['eV'], # coords={'eV':phi[:,0]}) # sim.attrs['sza'] = np.degrees(glowfort.cglow.sza) # # sim['tez'] = xarray.DataArray(glowfort.cglow.tez, # dims=['z_km'], coords={'z_km':z_km}) # %% production and loss rates # prate = prate.T; lrate=lrate.T #fortran to C ordering 2x170x20, only first 12 columns are used # # #column labels by inspection of fortran/gchem.f staring after "DO 150 I=1,JMAX" (thanks Stan!) # sim['prates'] = xarray.DataArray(prate[1,:,:12], #columns 12:20 are identically zero # dims=['z_km','reaction'], # coords={'z_km':z_km, # 'reaction':['O+(2P)','O+(2D)','O+(4S)','N+','N2+','O2+','NO+', # 'N2(A)','N(2P)','N(2D)','O(1S)','O(1D)']} # ) # # sim['lrates'] = xarray.DataArray(lrate[1,:,:12], #columns 12:20 are identically zero # dims=['z_km','reaction'], # coords={'z_km':z_km, # 'reaction':['O+(2P)','O+(2D)','O+(4S)','N+','N2+','O2+','NO+', # 'N2(A)','N(2P)','N(2D)','O(1S)','O(1D)']} # ) # # sim['sion'] = xarray.DataArray(glowfort.cglow.sion, # dims=['gas','z_km'], # coords={'gas':['O','O2','N2'], # 'z_km':z_km}) return sim
def main(): print(sd.find_nearest([10, 15, 12, 20, 14, 33], [32, 12.01])) print(INCORRECTRESULT_using_bisect([10, 15, 12, 20, 14, 33], [32, 12.01]))
#!/usr/bin/env python3 import numpy as np from bisect import bisect import sciencedates as sd def INCORRECTRESULT_using_bisect(x, X0): # pragma: no cover X0 = np.atleast_1d(X0) x.sort() ind = [bisect(x, x0) for x0 in X0] x = np.asanyarray(x) return np.asanyarray(ind), x[ind] print(sd.find_nearest([10, 15, 12, 20, 14, 33], [32, 12.01])) print(INCORRECTRESULT_using_bisect([10, 15, 12, 20, 14, 33], [32, 12.01]))