EXTRACTING NETCDF DATA BASED ON TIME
Show older comments
Good afternoon:
I am operating on a NetCDF file that contains data for 20 variables over a period of 8 months. This is too much data, so I am trying to extract data based on the time of day. That is, to extract data for all variables from 11pm to 4am for each day in the data file. I have been able to pull out the date / time in the format "dd-mmm-yyyy hh:mm:ss". I can extract and work on ranges of time, but not a range of time per day, for many days.
I can see in my head how to do this, but I am unsure of an efficient way to code it. Experimenting with different time functions, (datenum,hours, datetime, datevec) with other structure and NetCDF tools have been unsucessful. I could use a shove in the right direction. Thank you.
Accepted Answer
More Answers (2)
Tanziha Mahjabin
on 29 Jan 2020
Edited: Walter Roberson
on 29 Jan 2020
Hi,
I want to cut some time from a bid data, using ncread(source,varname,start,count).
for your information,
UCUR_sd
Size: 69x69x45588
Dimensions: J,I,TIME
Datatype: single
Attributes:
long_name = 'Standard deviation of sea water velocity U component values in 1 hour.'
units = 'm s-1'
valid_min = -10
valid_max = 10
cell_methods = 'TIME: standard_deviation'
coordinates = 'TIME LATITUDE LONGITUDE'
_FillValue = 999999
ancillary_variables = 'NOBS1 NOBS2 UCUR_quality_control'
Now if i write,
u=ncread(ncfile,'UCUR',[1 1 1],[Inf Inf 44931]);
it takes the command as the start time is from the start.
But what should i write if i want cut the time from somewhere middle?
I tried to define index,
ind=find(time>=datenum(2017,02,16,0,0,0)&time<=datenum(2017,02,17,0,0,0))
u=ncread(ncfile,'UCUR',[1 1 ind],[Inf Inf 44931]);
But it is not working. Any helpful suggestion please.
1 Comment
Walter Roberson
on 29 Jan 2020
netcdf times are never in MATLAB serial datenum . Instead they are in some time units relative to a particular epoch that is defined in the attributes, such as "seconds since Jul 1, 1983 00:00:00 UTC" . You need to examine the attributes for the TIME coordinate and do the conversion.
Tanziha Mahjabin
on 30 Jan 2020
Hi Walter,
Thanks for the comment. I did the conversion.
ncfile='IMOS_aggregation_20200124T074252Z.nc';
rtime=ncread(ncfile,'TIME');
time=datenum(rtime+datenum(1950,1,1,0,0,0));
When i write something like this, ru=ncread(ncfile,'UCUR',[1 1 1],[Inf Inf 931]); it works as the time starts from the beginning.
But i want to start the time from somewhere else as i mentioned in my question. So i defined index and try to start according to that.
ind=find(time>=datenum(2017,02,16,0,0,0)&time<=datenum(2017,02,17,0,0,0))
u=ncread(ncfile,'UCUR',[1 1 ind],[Inf Inf 44931]);
It didn't work.
8 Comments
Walter Roberson
on 30 Jan 2020
Is the time in the file days since that particular date? Not impossible for netcdf but tends to be a different time unit.
Tanziha Mahjabin
on 30 Jan 2020
no, it is hourly average.
Walter Roberson
on 30 Jan 2020
You coded
time=datenum(rtime+datenum(1950,1,1,0,0,0));
When you used datenum(1950,1,1,0,0,0) you would have gotten back a MATLAB serial date number, which would be in full days since Jan 1 0000 . When you add rtime to that, you are adding rtime days, so for example 27 would be 27 days after the base time, not 27 hours. You would have to use
time=datenum(rtime/24+datenum(1950,1,1,0,0,0));
However, unless you have special reason otherwise, I would recommend that you switch to using datetime objects:
time = datetime(1950,1,1,0,0,0)) + hours(rtime);
ind = isbetween(time, datetime(2017,02,16,0,0,0), datetime(2017,02,17,0,0,0));
Tanziha Mahjabin
on 30 Jan 2020
Sorry to bother you again. i tried both, but they didn't work. they are giving empty matrix for ind.
I guess because they are already hourly values.
If i write according to my code, ind=find(time>=datenum(2017,02,16,0,0,0)&time<=datenum(2017,02,17,0,0,0))
it gives me the correct count numbers during 16Feb2017 to 17Feb2017.
only it doesn't work when i input it in this line:
u=ncread(ncfile,'UCUR',[1 1 ind],[Inf Inf 44931]);
Walter Roberson
on 30 Jan 2020
ncread cannot read selected indices from an array, except that it can read a consecutive subsection.
mask = time>=datenum(2017,02,16,0,0,0) & time<=datenum(2017,02,17,0,0,0);
firstind = find(mask,1,'first');
lastind = find(mask,1,'last');
reduced_mask = mask(firstind:lastind);
most_u = ncread(ncfile,'UCUR',[1 1 firstind],[Inf Inf lastind-firstind+1]);
u = most_u(:,:,reduced_mask);
In the special case that time is sorted, the true entries in mask would be consecutive and the result of ncread could be used without further subselection.
mask = time>=datenum(2017,02,16,0,0,0) & time<=datenum(2017,02,17,0,0,0);
firstind = find(mask,1,'first');
lastind = find(mask,1,'last');
u = ncread(ncfile,'UCUR',[1 1 firstind],[Inf Inf lastind-firstind+1]);
Tanziha Mahjabin
on 30 Jan 2020
Edited: Walter Roberson
on 24 Oct 2022
I did manage to do it. Thank you for your time.
ncfile='IMOS_aggregation_20200124T074252Z.nc';
time=ncread(ncfile,'TIME');
begin = datenum('01 January 1950 00:00:00');
time=time+begin;
date_start=datestr(time(1));
date_end=datestr(time(end));
t0=find((datenum('16 February 2017 00:00:00'))==time);
t1=find((datenum('16 February 2017 23:00:00'))==time);
mtime=time(t0:t1);
date=datestr(mtime);
coo=0; nt=length(mtime);
for i=1:nt;
coo=coo+1;
% get each hours data
rtime=datenum(mtime(i));
[y m d hr min sec]=datevec(rtime);
start=datenum(y,m,d,hr,0,0);
ru=single(ncread(ncfile,'UCUR',[1 1 t0-1],[Inf Inf nt]));
Walter Roberson
on 30 Jan 2020
I don't think you want that read inside a for loop??
Mehak S
on 8 Apr 2024
Why 't0-1' and not t0 while reading the file?
Categories
Find more on Standard File Formats in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!