I have to make spatial plots from a bunch of WRFout files that I have. Currently, I am using following lines of code to print the respective times for each spatial plot
#..Load packages
import os
import netCDF4
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap,addcyclic,cm,shiftgrid
from wrf import getvar,get_basemap,to_np,latlon_coords
#..Read the files
fpath = sorted(glob.glob("/path/wrfout_d01_2017-03-02_00:00:00"))
with netCDF4.Dataset(fpath, 'r') as fin:
#..Read variables
p = getvar(fin,'pressure')
times = getvar(fin,'times',meta=False)
#..Make the pressure plot
fig = plt.figure()
mp = get_basemap(p)
x,y = mp(to_np(lons),to_np(lats))
cntrs = mp.contourf(x,y,p,cmap='jet')
plt.title(str(to_np(times))[0:-10])
plt.show()
The times variable gives time in the format 2017-03-02T00:00:00.000000000.
The line of code plt.title(str(to_np(times))[0:-10]) prints the time as 2017-03-02T00:00:00, which is a UTC time. But, I want it to be printed as 2017-03-01 17:00:00, which is the local time (UTC- 7 hours).
Thanks in advance, any suggestions will be highly appreciated.
You can use pandas to do the conversion.You can choose the timezone that works for you.
Just added the snippet thats useful.
import pandas as pd
#..Read variables
...
times = getvar(fin,'times',meta=False)
mountainTime = pd.Timestamp(times,tz='US/Mountain')
#..Make the pressure plot
...
plt.title(str(mountainTime)[0:-6])
This might help.
import datetime
dt=datetime.datetime.strptime("2017-03-02T00:00:00", "%Y-%m-%dT%H:%M:%S") #Get your datetime object
dt=dt.replace(tzinfo=datetime.timezone.utc) #Convert it to an aware datetime object in UTC time.
print(dt) #You do not need this line. For show only :P
dt=dt.astimezone() #Convert it to your local timezone
print(dt.strftime("%Y-%m-%d %H:%M:%S"))
Output:
2017-03-02 00:00:00+00:00
2017-03-02 05:30:00
Now my timezone is UTC+5:30 (India). So, showing that. Yours should give your.
Related
Having searched through similar questions for a possible solution on Stackoverflow, non seems to address this particular challenge. After running the code, I was getting the TypeError: **'.dt' accessor only available for DataArray with datetime64 timedelta64 dtype or for arrays containing cftime datetime objects.. I have tried tweaking the code differently to no avail, any help at this point will be greatly appreciated, please. Thanks
import os
from netCDF4 import Dataset
import xarray as xr
import numpy as np
import pandas as pd
from datetime import datetime
#import ffmpeg
from IPython.display import HTML
from matplotlib import pyplot as plt
from matplotlib import animation
import ipynb
import cartopy.crs as ccrs
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
%run ../functions.ipynb
# Load Metop-A GOME-2 Level 3 AAI data
file = 'ESACCI-AEROSOL-L3-AAI-GOME2A-1D-20210205-fv1.8.nc'
aai_gome2a = xr.open_dataset(file)
# Load Metop Metop-A, -B & -C netcdf data
ds_a = xr.open_mfdataset('ESACCI-AEROSOL-L3-AAI-GOME2A-1D-2021020*.nc',
concat_dim='time',
combine='nested')
ds_b = xr.open_mfdataset('ESACCI-AEROSOL-L3-AAI-GOME2B-1D-2021020*.nc',
concat_dim='time',
combine='nested')
ds_c = xr.open_mfdataset('ESACCI-AEROSOL-L3-AAI-GOME2C-1D-2021020*.nc',
concat_dim='time',
combine='nested')
# display the variable of interest, i.e absorbing_aerosol_index
aai_a=ds_a['absorbing_aerosol_index']
aai_b=ds_b['absorbing_aerosol_index']
aai_c=ds_c['absorbing_aerosol_index']
# Concatenate the data from the three satellites Metop-A, -B and -C
aai_concat = xr.concat([aai_a,aai_b,aai_c], dim='satellite')
# Retrieve time coordinate information and assign time coordinates for the time dimension
start_day = aai_gome2a.description.split()[4]
time_coords = pd.date_range(datetime.strptime(start_day,'%d-%m-%Y'), periods=len(aai_concat.time), freq='d').strftime("%Y-%m-%d").astype('datetime64[ns]')
# Combine AAI data from the three satellites Metop-A, -B and -C onto one single grid
aai_combined = aai_concat.mean(dim='satellite')
# Visualize AAI data with data from the three satellites Metop-A, -B and C combined on one single grid
visualize_pcolormesh(data_array=aai_combined[1,:,:],
longitude=aai_combined.longitude,
latitude=aai_combined.latitude,
projection=ccrs.PlateCarree(),
color_scale='afmhot_r',
unit=' ',
long_name=aai_a.long_name + ' ' + str(aai_combined.time[0].dt.strftime('%Y-%m-%d').data),
vmin=0,
vmax=5,
lonmin=-50,
lonmax=36,
latmin=0,
latmax=70.,
set_global=False)
See expected output here: https://www.canva.com/design/DAE-vuWH6Ak/view
I am following this tutorial while learing Python (https://towardsdatascience.com/how-tracking-apps-analyse-your-gps-data-a-hands-on-tutorial-in-python-756d4db6715d).
I am at the step where I want to plot 'time' and 'elevation'. But when I do this with:
plt.plot(df['time'], df['ele'])
plt.show()
I get the error "'NoneType' object has no attribute 'offset'". If I plot 'longitude' and 'latitude' everything works fine.
I cannot find a way to solve this problem by myself.
This is "my" code so far:
import gpxpy
import matplotlib.pyplot as plt
import datetime
from geopy import distance
from math import sqrt, floor
import numpy as np
import pandas as pd
import chart_studio.plotly as py
import plotly.graph_objects as go
import haversine
#Import Plugins
gpx_file = open('01_Karlsruhe_Schluchsee.gpx', 'r')
gpx = gpxpy.parse(gpx_file)
data = gpx.tracks[0].segments[0].points
## Start Position
start = data[0]
## End Position
finish = data[-1]
df = pd.DataFrame(columns=['lon', 'lat', 'ele', 'time'])
for point in data:
df = df.append({'lon': point.longitude, 'lat' : point.latitude,
'ele' : point.elevation, 'time' : point.time}, ignore_index=True)
print(df)
plt.plot(df['time'], df['ele'])
plt.show()
Picture of my dataframe
Removing the timezone from your 'time' column might do the trick. You can do this with tz_localize. Note that you have to call method dt to access column datetime properties:
df['time'] = df['time'].dt.tz_localize(None)
The problem is that the times in gpxpy have a time zone of SimpleTZ('Z'), which I think is their own implementation of the tzinfo abstract base class. That makes it "aware" as opposed to "naive" but apparently doesn't allow getting the offset.
See https://github.com/tkrajina/gpxpy/issues/209.
I fixed it as follows and also got the time zone for the first location in a track. (The track may have been done is a different time zone than local.)
import datetime
from zoneinfo import ZoneInfo
from timezonefinder import TimezoneFinder
def get_data(gpx):
'''Currently Only does the first track and first segment'''
tzf = TimezoneFinder()
# Use lists for the data not a DataFrame
lat = []
lon = []
ele = []
time = []
n_trk = len(gpx.tracks)
for trk in range(n_trk):
n_seg = len(gpx.tracks[trk].segments)
first = True # Flag to get the timezone for this track
for seg in range(n_seg):
points = gpx.tracks[trk].segments[seg].points
for point in points:
if(first):
# Get the time zone from the first point in first segment
tz_name = tzf.timezone_at(lng=point.longitude, lat=point.latitude)
first = False
lat.append(point.latitude)
lon.append(point.longitude)
ele.append(point.elevation)
try:
new_time = point.time.astimezone(ZoneInfo(tz_name))
except:
new_time = point.time.astimezone(ZoneInfo('UTC'))
time.append(new_time)
return lat, lon, ele, time
With these changes the plots in PyPlot work as expected.
ZoneInfo is only available as of Python 3.9, and on Windows you also have to install tzdata (pip install tzdata) for ZoneInfo to work. For earlier versions you could do essentially the same thing using pytz.
I am reading in data from a text file which contains data in the format (date time; microVolts):
e.g. 07.03.2017 23:14:01,000; 279
And I wish to plot a graph using matplotlib by capturing only the time (x-axis) and plotting it against microVolts (y-axis). So far, I've managed to extract the time element from the string and convert it into datetime format (shown below).
I tried to append each value of time into x to plot, but the program just freezes and displays nothing.
Here is part of the code:
from datetime import datetime
import matplotlib.pyplot as plt
ecg = open(file2).readlines()
x = []
for line in range(len(ecg)):
ecgtime = ecg[7:][line][:23]
ecgtime = datetime.strptime(ecgtime, '%d.%m.%Y %H:%M:%S,%f')
x.append(ecgtime.time())
I'm aware the datetime format is causing the issue but I can't figure out how to convert it into float/int as it says:
'invalid literal for float(): 23:14:01,000'
I have no reputation for comment than I have to answer.
datetime.datetime.time() converts to datetime.time object, you need float.
Could you try datetime.datetime.timestamp()?
See last line:
from datetime import datetime
import matplotlib.pyplot as plt
ecg = open(file2).readlines()
x = []
for line in range(len(ecg)):
ecgtime = ecg[7:][line][:23]
ecgtime = datetime.strptime(ecgtime, '%d.%m.%Y %H:%M:%S,%f')
x.append(ecgtime.timestamp())
EDIT: timestamp() is available sine Python 3.3. For Python 2 you can use
from time import mktime
...
x.append(mktime(ecgtime.timetuple()))
I am trying to graph the time needed for python to computer the factorial of integers between 1 and 150.
My script calculates the different time just fine and I am able to print them but when I try to graph it I am getting a value error, saying that my sequence is too large.
How can I solve this?
This is my code:
import numpy as np
import time
start_time = time.time()
n = np.linspace(1,151)
for i in range(151) :
np.math.factorial(i)
dt = ((time.time()-start_time))
plot(n,dt)
You need to collect your run times in a list dt to plot them:
import numpy as np
import timeit
from matplotlib import pyplot as plt
start_time = timeit.default_timer()
r = range(1, 151)
dt = []
for i in r:
np.math.factorial(i)
dt.append(timeit.default_timer()-start_time)
plt.plot(r, dt)
Result:
I'm using matplotlib to plot some data imported from CSV files. These files have the following format:
Date,Time,A,B
25/07/2016,13:04:31,5,25550
25/07/2016,13:05:01,0,25568
....
01/08/2016,19:06:43,0,68425
The dates are formatted as they would be in the UK, i.e. %d/%m/%Y. The end result is to have two plots: one of how A changes with time, and one of how B changes with time. I'm importing the data from the CSV like so:
import matplotlib
matplotlib.use('Agg')
from matplotlib.mlab import csv2rec
import matplotlib.pyplot as plt
from datetime import datetime
import sys
...
def analyze_log(file, y):
data = csv2rec(open(file, 'rb'))
fig = plt.figure()
date_vec = [datetime.strptime(str(x), '%Y-%m-%d').date() for x in data['date']]
print date_vec[0]
print date_vec[len(date_vec)-1]
time_vec = [datetime.strptime(str(x), '%Y-%m-%d %X').time() for x in data['time']]
print time_vec[0]
print time_vec[len(time_vec)-1]
datetime_vec = [datetime.combine(d, t) for d, t in zip(date_vec, time_vec)]
print datetime_vec[0]
print datetime_vec[len(datetime_vec)-1]
y_vec = data[y]
plt.plot(datetime_vec, y_vec)
...
# formatters, axis headers, etc.
...
return plt
And all was working fine before 01 August. However, since then, matplotlib is trying to plot my 01/08/2016 data points as 2016-01-08 (08 Jan)!
I get a plotting error because it tries to plot from January to July:
RuntimeError: RRuleLocator estimated to generate 4879 ticks from 2016-01-08 09:11:00+00:00 to 2016-07-29 16:22:34+00:00:
exceeds Locator.MAXTICKS * 2 (2000)
What am I doing wrong here? The results of the print statements in the code above are:
2016-07-25
2016-01-08 #!!!!
13:04:31
19:06:43
2016-07-25 13:04:31
2016-01-08 19:06:43 #!!!!
Matplotlib's csv2rec function parses your dates already and tries to be intelligent when it comes to parsing dates. The function has two options to influence the parsing, dayfirst should help here:
dayfirst: default is False so that MM-DD-YY has precedence over DD-MM-YY.
yearfirst: default is False so that MM-DD-YY has precedence over YY-MM-DD.
See http://labix.org/python-dateutil#head-b95ce2094d189a89f80f5ae52a05b4ab7b41af47 for further information.
You're using strings in %d/%m/%Y format but you've given the format specifier as %Y-%m-%d.