├── .gitignore
├── LICENSE
├── README.md
├── docs
├── creating_forcings.md
├── img
│ ├── basin_mask.png
│ ├── disaggregated_forcings.png
│ ├── forcings.png
│ ├── precip_out.png
│ ├── soilpars.png
│ └── swe.png
├── index.md
├── subsetting.md
├── tuolumne_example.md
├── tuolumne_image_classic_comparison.md
└── tuolumne_image_test.md
├── examples
├── global_param_WY2002-2005.txt
├── global_param_disagg.txt
├── tuolumne_example_L2013.m
└── tuolumne_example_VICGlobal.m
├── mkdocs.yml
├── site
├── 404.html
├── css
│ ├── theme.css
│ └── theme_extra.css
├── fonts
│ ├── Lato
│ │ ├── lato-bold.eot
│ │ ├── lato-bold.ttf
│ │ ├── lato-bold.woff
│ │ ├── lato-bold.woff2
│ │ ├── lato-bolditalic.eot
│ │ ├── lato-bolditalic.ttf
│ │ ├── lato-bolditalic.woff
│ │ ├── lato-bolditalic.woff2
│ │ ├── lato-italic.eot
│ │ ├── lato-italic.ttf
│ │ ├── lato-italic.woff
│ │ ├── lato-italic.woff2
│ │ ├── lato-regular.eot
│ │ ├── lato-regular.ttf
│ │ ├── lato-regular.woff
│ │ └── lato-regular.woff2
│ ├── RobotoSlab
│ │ ├── roboto-slab-v7-bold.eot
│ │ ├── roboto-slab-v7-bold.ttf
│ │ ├── roboto-slab-v7-bold.woff
│ │ ├── roboto-slab-v7-bold.woff2
│ │ ├── roboto-slab-v7-regular.eot
│ │ ├── roboto-slab-v7-regular.ttf
│ │ ├── roboto-slab-v7-regular.woff
│ │ ├── roboto-slab-v7-regular.woff2
│ │ └── roboto-slab.eot
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.svg
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ └── fontawesome-webfont.woff2
├── img
│ ├── basin_mask.png
│ ├── disaggregated_forcings.png
│ ├── favicon.ico
│ ├── forcings.png
│ ├── precip_out.png
│ ├── soilpars.png
│ └── swe.png
├── index.html
├── js
│ ├── jquery-2.1.1.min.js
│ ├── modernizr-2.8.3.min.js
│ └── theme.js
├── search.html
├── search
│ ├── lunr.js
│ ├── main.js
│ ├── search_index.json
│ └── worker.js
├── sitemap.xml
├── sitemap.xml.gz
└── tuolumne_example
│ └── index.html
└── vicmatlab
├── forcings
├── aggregate_forcing.m
├── convert_forcing.m
├── load_ascii_forcings.m
├── make_netcdf_forcing.m
├── save_forcings.m
├── subset_forcings.m
├── subset_forcings_time.m
├── subset_forcings_to_spf.m
├── upscale_forcing.m
├── upscale_forcing2.m
└── write_netcdf_forcing.m
├── general
├── check_water_year.m
├── georefobj2mat.m
├── geotiffread2.m
├── grid2xyz.m
├── imagescnan.m
├── plotraster.m
└── xyz2grid.m
├── outputs
├── annual_average.m
├── calc_basin_avg_ts.m
├── calc_summed_QdQb.m
├── get_vic_run_metadata.m
├── get_vic_run_metadata2.m
├── load_classic_mode_outputs.m
├── load_vic_output.m
├── load_vic_output2.m
├── load_vic_output_image.m
├── make_results_struct_wb.m
├── mask_results_to_bb.m
├── myKGE.m
├── myNSE.m
├── myRMSE.m
├── parload.m
├── subset_outputs_to_spf.m
├── vic_output_lookup_table
└── vic_outputs_names_table.ods
├── parallel
├── read_global_param_file.m
├── set_up_parallel.m
├── set_up_parallel_wrapper.m
└── write_global_param_file.m
├── routing
├── convert_routing_inputs.m
└── remove_headers.m
├── soils
├── get_soil_var_names.m
├── make_soil_tifs.m
├── myregrid.m
├── reassign_soil_parameters.m
├── subset_soils.m
├── subset_soils2.m
├── upscale_soils.m
├── write_soil_moisture_to_spf.m
└── write_soils.m
├── subsetting
├── _Example.pdf
├── basin_mask2coordinate_list.m
├── crop_dem.m
├── georefobj2mat.m
├── geotiffread2.m
├── get_soil_var_names.m
├── grid2xyz.m
├── make_cropping_rectangle.m
├── prepb4_subset.R
├── readme.txt
├── subset_domain.m
├── subset_image_wrapper.m
├── subset_netcdf_w_geotiffmask.m
├── subset_parameter.m
├── subset_soils.m
├── subset_soils_to_coords.m
├── subset_wrapper.m
├── upper_tuolumne_basin_merc.tif
├── upper_tuolumne_basin_wgs.tif
├── write_soils.m
└── xyz2grid.m
├── upscale_vegpars.m
└── utility
├── GetCoords.m
├── basin_mask2coordinate_list.m
├── calc_water_year_average.m
├── cfs2cms.m
├── classic2image.m
├── classic_outputs2image.m
├── crop_time_series.m
├── crop_ts.m
├── daily_to_monthly.m
├── find_closest.m
├── find_line.m
├── get_coordinates_from_VIC_file.m
├── get_vic_header.m
├── getlatlon.m
├── hourly_to_daily.m
├── latlon_from_raster.m
├── load_streamflow_data.m
├── match_coords.m
├── match_time_series.m
├── mmday2cms.m
├── padfill.m
├── read_usgs.m
├── remove_empty_rowcol.m
├── rescale_mean.m
└── upscale_raster.m
/.gitignore:
--------------------------------------------------------------------------------
1 | *.sh
2 | Old/
3 | # *.R
4 | data/
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## VICMATLAB
2 | Matlab functions for preparing inputs for - and processing outputs from - the Variable Infiltration Capacity (VIC) model. Has functionality for the following VIC versions: VIC-4.2.d, VIC-5 Classic Driver, and VIC-5 Image Driver.
3 |
4 | ## Tutorial
5 |
6 | See the documentation page --- [https://jschap1.github.io/VICMATLAB/](https://jschap1.github.io/VICMATLAB/) --- for a tutorial.
7 |
8 | ### MATLAB functions provided in VICMATLAB
9 |
10 | #### Main functions
11 |
12 | * **subset_forcings**: Subsets forcings to a particular basin.
13 |
14 | * **load_ascii_forcings**: Loads ASCII meteorological forcing files into MATLAB.
15 |
16 | * **get_vic_run_metadata**: Gets metadata, such as variable names, length of simulation, etc. from a VIC simulation.
17 |
18 | * **load_vic_output**: Loads a VIC output variable, such as SWE or net radiation, into MATLAB.
19 |
20 | * **subset_soils**: Clips soil parameter file to basin extent.
21 |
22 | * **classic2image** (credit to Dongyue Li): Converts VIC-4 or VIC-5 Classic Driver inputs to NetCDF format for use with the VIC-5 Image Driver.
23 |
24 | * **plotraster**: Main plotting function to make maps of meteorological variables, VIC outputs, soil parameters, etc.
25 |
26 | #### Utility functions
27 |
28 | * save_forcings
29 | * georefobj2mat
30 | * geotiffread2
31 | * get_soil_var_names
32 | * write_soils
33 | * get_coordinates_from_VIC_file
34 | * get_vic_header
35 | * GetCoords
36 | * grid2xyz (from MATLAB File Exchange)
37 | * xyz2grid (from MATLAB File Exchange)
38 | * imagescnan (from MATLAB File Exchange)
39 |
40 | ### Requirements
41 | MATLAB R2016a or later
42 | Mapping Toolbox
43 | Image Processing Toolbox
44 |
45 | ### Recommended
46 | Parallel Computing Toolbox
47 | R, RStudio
48 | raster, rgeos, and rgdal packages for R
49 |
--------------------------------------------------------------------------------
/docs/creating_forcings.md:
--------------------------------------------------------------------------------
1 | # Creating meteorological forcing input files
2 |
3 | The VIC model requires meteorological forcing input files containing time series of precipitation, temperature, and other meteorological variables at each grid cell. This article describes preparation of meteorological forcing files for the Stehekin domain, using the Livneh et al. (2013) meteorological input data.
4 |
5 | 1. Subset precipitation, wind speed, and minimum and maximum temperature data to the basin.
6 | 1. Run VIC-4 as a meteorological disaggregator to calculate temperature, air pressure, vapor pressure, and downwelling shortwave and longwave radiation.
7 | 1. Convert forcing files from classic mode to image mode.
8 |
9 | ## Subset forcings to Stehekin basin
10 |
11 | (This will be done in the ESSD/codes directory, since part of this project is to figure out what is wrong with my image mode forcing files, if anything.)
12 |
13 | Get Stehekin domain
14 | Run VICMATLAB subsetting code
15 |
16 | See stehekin_wrapper.m.
17 |
18 | ## Run VIC as disaggregator
19 |
20 | Set up and run VIC-4 model for Stehekin.
21 |
22 | Data are in `/hdd/ESSD/data/stehekin`. The Stehekin soil, vegetation, and elevation band parameter files are in the `~/Documents/Software/vic_sample_data` directory. However, these will not work because they are not at the same 1/16 degree resolution as the forcing files. Instead, I am subsetting the VICGlobal soil parameter file.
23 |
24 | ## Convert from classic to image mode
25 |
26 | Run VICMATLAB conversion code
27 |
28 | ## Run VIC in classic and image mode
29 |
30 | Run VIC in classic mode
31 | Run VIC in image mode
32 | Confirm that outputs are the same from both modes
--------------------------------------------------------------------------------
/docs/img/basin_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/docs/img/basin_mask.png
--------------------------------------------------------------------------------
/docs/img/disaggregated_forcings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/docs/img/disaggregated_forcings.png
--------------------------------------------------------------------------------
/docs/img/forcings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/docs/img/forcings.png
--------------------------------------------------------------------------------
/docs/img/precip_out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/docs/img/precip_out.png
--------------------------------------------------------------------------------
/docs/img/soilpars.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/docs/img/soilpars.png
--------------------------------------------------------------------------------
/docs/img/swe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/docs/img/swe.png
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # VICMATLAB
2 |
3 | A MATLAB toolbox for processing inputs and outputs for the Variable Infiltration Capacity (VIC) model.
4 |
5 | Includes subsetting functions for the VICGlobal soil and vegetation parameters. VICMATLAB code can be downloaded from the author's [Github][vicmatlab] page.
6 |
7 | [vicmatlab]:https://github.com/jschap1/VICMATLAB
--------------------------------------------------------------------------------
/docs/subsetting.md:
--------------------------------------------------------------------------------
1 | # Subsetting VICGlobal
2 |
3 | This documents explains how to use the subsetting codes in VICMATLAB to subset VICGlobal to your study area. The subsetting codes are also included separately with the VICGlobal dataset.
4 |
5 | Written: August 4, 2020 JRS
6 | Dependencies: MATLAB Mapping Toolbox.
7 |
8 | 1. Download VICGlobal from its [link][vicglobal] on Zenodo
9 | 2. Extract the VICGlobal files from the relevant archive (classic or image). Warning: the image mode parameter file is very large after extracting (about 140 GB).
10 | 3. Choose a study area. You should have either a shapefile, a raster, or a list of coordinates defining your study area.
11 |
12 | ## Classic mode
13 |
14 | Subset the soil parameter file to your study basin. Also generates Geotiffs of the soil parameters for easy visualization.
15 |
16 | ```matlab
17 | % add path to the subsetting codes
18 | addpath('${your_path}/subsetting/')
19 |
20 | % Load full soil parameter file
21 | soilfile = '${your_path}/Classic/soils_3L_MERIT.txt';
22 | disp('Loading soil parameter file')
23 | soils = load(soilfile);
24 | disp('Soil parameter file has been loaded')
25 |
26 | % Subset the soil parameter file
27 | extent = '${your_path}/colo_mask.tif';
28 | grid_decimal = 5; % precision of VIC grid cells
29 | outformat = '3l'; % may be '2l', 3l' or 'livneh'
30 | outname = '${your_path}/colo_soils_VG_v1.6.txt';
31 |
32 | generate_tif = 1; % option to generate tifs of soil parameters
33 | setup = '3L-no-org-frost-msds'; % can be 2L, 2L-no-org-fs-july_tavg, 3L, 3L-no-org-frost-msds, or livneh
34 |
35 | soils_subset = subset_soils(soils, extent, outname, outformat, grid_decimal, generate_tif, setup);
36 | ```
37 |
38 | ## Image mode
39 |
40 | Subset the image mode domain and parameter files to your study basin. Note that this requires a lot of RAM because of the large size of the VICGlobal image mode parameter file. For the Upper Colorado River Basin (7833 1/16 degree grid cells), I found that 16 GB was not enough RAM, but 48 GB is enough.
41 |
42 | ```matlab
43 | % add path to the subsetting codes
44 | addpath('${your_path}/subsetting/')
45 |
46 | % Specify output directory and basin name
47 | outdir = '${your_path}/subset_image/';
48 | basinname = 'ucrb';
49 | extent = '${your_path}/colo_mask.tif';
50 |
51 | vicglobaldomain = '${your_path}/Image/VICGlobal_domain.nc';
52 | vicglobalparams = '${your_path}/Image/VICGlobal_params.nc';
53 | subset_domain(ucrb_tif, vicglobaldomain, 'ucrb_domain.nc'))
54 | subset_parameter(ucrb_tif, vicglobalparams, 'ucrb_params.nc'));
55 | ```
56 |
57 | # List of all functions
58 |
59 | * subset_domain
60 | * subset_parameter
61 | * geotiffread2
62 | * georefobj2mat
63 | * basin_mask2coordinate_list
64 | * xyz2grid
65 | * get_soil_var_names
66 | * subset_soils
67 | * write_soils
68 |
69 | [vicglobal]:https://zenodo.org/record/3475602
--------------------------------------------------------------------------------
/docs/tuolumne_image_classic_comparison.md:
--------------------------------------------------------------------------------
1 | # Tuolumne basin image mode/classic mode comparison
2 |
3 | Files are in `/home/jschap/Documents/Codes/VICMATLAB/examples/`. Demo the subsetting codes and publish the instructions in a Markdown file, which is available for reference from the VICGlobal Zenodo respository. Compare Classic/Image mode outputs for Tuolumne basin.
4 |
5 | Simulation uses the Livneh et al. (2013) meteorological forcing data, and is for the calendar years 2009-2011, with no accounting for soil moisture spin-up. Energy balance mode with five snowbands.
6 |
7 | See MATLAB wrapper for the comparison. Will write this up here as a Markdown file, once it is running.
8 |
9 |
10 | ```bash
11 | ./vic_classic.exe -g /home/jschap/Documents/Codes/VICMATLAB/data/VICGlobal/global_param.txt
12 | ```
13 |
14 |
15 | ```bash
16 | ./vic_classic.exe -g /home/jschap/Documents/Codes/VICMATLAB/data/VICGlobal/tuolumne_image_global.txt
17 | ```
18 |
19 | The basin average and time average values look very similar. However, I checked baseflow for a particular grid cell, and it was pretty different. Maybe there is something to do with the global parameter files? No, it doesn't look like there are any major differences there.
20 |
21 | ## Setup for classic mode
22 |
23 | * Energy balance mode, hourly time steps.
24 | * Frozen soils set to false
25 | * Implicit false
26 | * exp_trans false
27 | * 2 m wind height
28 | * 5 snow bands
29 | * July avgT supplied
30 | * ARNO baseflow formulation
31 |
32 | ## Setup for image mode
33 |
34 | * Energy balance mode, hourly time steps
35 | * Frozen soils set to false
36 | * Wind measurement height read from NetCDF file. Might be 2 m or 10 m
37 | * 5 snow bands
38 | * July avgT supplied
39 | * ARNO baseflow formulation
40 |
41 | This makes me think that maybe the soil parameters are different between the image mode and classic mode formats. Look at plots of soil parameters from each source and confirm that they are in fact the same.
42 |
43 | OK, I figured out the problem. The tuolumne_image NetCDF parameters use the old rmin and r0 values, and likely use the same albedo, fractional canopy cover, and LAI (non-snow-free), so they don't match the v1.6 vegetation parameters, which I updated this summer.
44 |
45 | ## Revisiting with updated image mode parameters
46 |
47 | ### Subset image mode parameters to the Tuolumne basin
48 |
49 | Transfer input files to Atlantic.
50 |
51 | ```bash
52 |
53 | scp /hdd/Data/VICParametersGlobal/VICGlobal/v1.6/Older_Versions/output_latest_aug14.tar.gz jschap@american.seas.ucla.edu:/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/
54 |
55 | scp /home/jschap/Documents/Codes/VICMATLAB/data/upptuo_mask.tif jschap@american.seas.ucla.edu:/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/sub/
56 |
57 | scp -r /hdd/Data/VICParametersGlobal/VICGlobal/continent_masks jschap@american.seas.ucla.edu:/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/sub/
58 |
59 | ```
60 |
61 | Run subsetting on Atlantic.
62 |
63 | ```matlab
64 |
65 | addpath(genpath('~/Documents/Codes/VICMATLAB/vicmatlab'))
66 |
67 | domain_name = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/sub/tuolumne_domain.nc';
68 |
69 | param_name = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/sub/tuolumne_params.nc';
70 |
71 | basinmaskname = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/sub/upptuo_mask.tif';
72 |
73 | global_domain = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/output_latest/VICGlobal_domain.nc';
74 |
75 | global_params = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/output_latest/VICGlobal_params.nc';
76 |
77 | subset_domain(basinmaskname, global_domain, domain_name)
78 | subset_parameter(basinmaskname, global_params, param_name)
79 |
80 | ```
81 |
82 | Also subset to continents.
83 |
84 | ```matlab
85 |
86 | cd('/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/sub/continent_masks/')
87 | basinmasknames = dir('*.tif');
88 | n = length(basinmasknames)
89 | for k=1:n
90 | basinmaskname = basinmasknames(k).name;
91 | param_name = [basinmaskname '_param.nc'];
92 | domain_name = [basinmaskname '_domain.nc'];
93 | subset_domain(basinmaskname, global_domain, domain_name)
94 | subset_parameter(basinmaskname, global_params, param_name)
95 | end
96 |
97 | ```
98 |
99 | Copy the Tuolumne parameters back to Atlantic
100 |
101 | ```bash
102 | scp jschap@american.seas.ucla.edu:/Volumes/HD3/VICParametersGlobal/VICGlobal/v1.6/sub/*.nc .
103 | ```
104 |
105 | Run the Tuolumne simulation in image mode.
106 |
107 |
108 | ```bash
109 | ./vic_image.exe -g /home/jschap/Documents/Codes/VICMATLAB/data/VICGlobal/tuolumne_image_global.txt > /home/jschap/Documents/Codes/VICMATLAB/data/VICGlobal/vic_image_log.txt
110 | ```
111 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: VICMATLAB
2 | nav:
3 | - Main: index.md
4 | - Example: tuolumne_example.md
5 | - Subsetting VICGlobal: subsetting.md
6 | theme: readthedocs
7 |
--------------------------------------------------------------------------------
/site/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | VICMATLAB
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
54 |
55 |
56 |
57 |
58 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | - Docs »
69 |
70 |
71 | -
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
404
83 |
84 |
Page not found
85 |
86 |
87 |
88 |
89 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/site/css/theme_extra.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Wrap inline code samples otherwise they shoot of the side and
3 | * can't be read at all.
4 | *
5 | * https://github.com/mkdocs/mkdocs/issues/313
6 | * https://github.com/mkdocs/mkdocs/issues/233
7 | * https://github.com/mkdocs/mkdocs/issues/834
8 | */
9 | .rst-content code {
10 | white-space: pre-wrap;
11 | word-wrap: break-word;
12 | padding: 2px 5px;
13 | }
14 |
15 | /**
16 | * Make code blocks display as blocks and give them the appropriate
17 | * font size and padding.
18 | *
19 | * https://github.com/mkdocs/mkdocs/issues/855
20 | * https://github.com/mkdocs/mkdocs/issues/834
21 | * https://github.com/mkdocs/mkdocs/issues/233
22 | */
23 | .rst-content pre code {
24 | white-space: pre;
25 | word-wrap: normal;
26 | display: block;
27 | padding: 12px;
28 | font-size: 12px;
29 | }
30 |
31 | /**
32 | * Fix code colors
33 | *
34 | * https://github.com/mkdocs/mkdocs/issues/2027
35 | */
36 | .rst-content code {
37 | color: #E74C3C;
38 | }
39 |
40 | .rst-content pre code {
41 | color: #000;
42 | background: #f8f8f8;
43 | }
44 |
45 | /*
46 | * Fix link colors when the link text is inline code.
47 | *
48 | * https://github.com/mkdocs/mkdocs/issues/718
49 | */
50 | a code {
51 | color: #2980B9;
52 | }
53 | a:hover code {
54 | color: #3091d1;
55 | }
56 | a:visited code {
57 | color: #9B59B6;
58 | }
59 |
60 | /*
61 | * The CSS classes from highlight.js seem to clash with the
62 | * ReadTheDocs theme causing some code to be incorrectly made
63 | * bold and italic.
64 | *
65 | * https://github.com/mkdocs/mkdocs/issues/411
66 | */
67 | pre .cs, pre .c {
68 | font-weight: inherit;
69 | font-style: inherit;
70 | }
71 |
72 | /*
73 | * Fix some issues with the theme and non-highlighted code
74 | * samples. Without and highlighting styles attached the
75 | * formatting is broken.
76 | *
77 | * https://github.com/mkdocs/mkdocs/issues/319
78 | */
79 | .rst-content .no-highlight {
80 | display: block;
81 | padding: 0.5em;
82 | color: #333;
83 | }
84 |
85 |
86 | /*
87 | * Additions specific to the search functionality provided by MkDocs
88 | */
89 |
90 | .search-results {
91 | margin-top: 23px;
92 | }
93 |
94 | .search-results article {
95 | border-top: 1px solid #E1E4E5;
96 | padding-top: 24px;
97 | }
98 |
99 | .search-results article:first-child {
100 | border-top: none;
101 | }
102 |
103 | form .search-query {
104 | width: 100%;
105 | border-radius: 50px;
106 | padding: 6px 12px; /* csslint allow: box-model */
107 | border-color: #D1D4D5;
108 | }
109 |
110 | /*
111 | * Improve inline code blocks within admonitions.
112 | *
113 | * https://github.com/mkdocs/mkdocs/issues/656
114 | */
115 | .rst-content .admonition code {
116 | color: #404040;
117 | border: 1px solid #c7c9cb;
118 | border: 1px solid rgba(0, 0, 0, 0.2);
119 | background: #f8fbfd;
120 | background: rgba(255, 255, 255, 0.7);
121 | }
122 |
123 | /*
124 | * Account for wide tables which go off the side.
125 | * Override borders to avoid wierdness on narrow tables.
126 | *
127 | * https://github.com/mkdocs/mkdocs/issues/834
128 | * https://github.com/mkdocs/mkdocs/pull/1034
129 | */
130 | .rst-content .section .docutils {
131 | width: 100%;
132 | overflow: auto;
133 | display: block;
134 | border: none;
135 | }
136 |
137 | td, th {
138 | border: 1px solid #e1e4e5 !important; /* csslint allow: important */
139 | border-collapse: collapse;
140 | }
141 |
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-bold.eot
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-bold.ttf
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-bold.woff
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-bold.woff2
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-bolditalic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-bolditalic.eot
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-bolditalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-bolditalic.ttf
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-bolditalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-bolditalic.woff
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-bolditalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-bolditalic.woff2
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-italic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-italic.eot
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-italic.ttf
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-italic.woff
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-italic.woff2
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-regular.eot
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-regular.ttf
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-regular.woff
--------------------------------------------------------------------------------
/site/fonts/Lato/lato-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/Lato/lato-regular.woff2
--------------------------------------------------------------------------------
/site/fonts/RobotoSlab/roboto-slab-v7-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/RobotoSlab/roboto-slab-v7-bold.eot
--------------------------------------------------------------------------------
/site/fonts/RobotoSlab/roboto-slab-v7-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/RobotoSlab/roboto-slab-v7-bold.ttf
--------------------------------------------------------------------------------
/site/fonts/RobotoSlab/roboto-slab-v7-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/RobotoSlab/roboto-slab-v7-bold.woff
--------------------------------------------------------------------------------
/site/fonts/RobotoSlab/roboto-slab-v7-bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/RobotoSlab/roboto-slab-v7-bold.woff2
--------------------------------------------------------------------------------
/site/fonts/RobotoSlab/roboto-slab-v7-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/RobotoSlab/roboto-slab-v7-regular.eot
--------------------------------------------------------------------------------
/site/fonts/RobotoSlab/roboto-slab-v7-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/RobotoSlab/roboto-slab-v7-regular.ttf
--------------------------------------------------------------------------------
/site/fonts/RobotoSlab/roboto-slab-v7-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/RobotoSlab/roboto-slab-v7-regular.woff
--------------------------------------------------------------------------------
/site/fonts/RobotoSlab/roboto-slab-v7-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/RobotoSlab/roboto-slab-v7-regular.woff2
--------------------------------------------------------------------------------
/site/fonts/RobotoSlab/roboto-slab.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/RobotoSlab/roboto-slab.eot
--------------------------------------------------------------------------------
/site/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/site/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/site/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/site/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/site/img/basin_mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/img/basin_mask.png
--------------------------------------------------------------------------------
/site/img/disaggregated_forcings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/img/disaggregated_forcings.png
--------------------------------------------------------------------------------
/site/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/img/favicon.ico
--------------------------------------------------------------------------------
/site/img/forcings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/img/forcings.png
--------------------------------------------------------------------------------
/site/img/precip_out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/img/precip_out.png
--------------------------------------------------------------------------------
/site/img/soilpars.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/img/soilpars.png
--------------------------------------------------------------------------------
/site/img/swe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/img/swe.png
--------------------------------------------------------------------------------
/site/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | VICMATLAB
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
63 |
64 |
65 |
66 |
67 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | - Docs »
78 |
79 |
80 |
81 | - Main
82 | -
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
VICMATLAB
93 |
A MATLAB toolbox for processing inputs and outputs for the Variable Infiltration Capacity (VIC) model.
94 |
Includes subsetting functions for the VICGlobal soil and vegetation parameters. VICMATLAB code can be downloaded from the author's Github page.
95 |
96 |
97 |
98 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | Next »
131 |
132 |
133 |
134 |
135 |
136 |
137 |
142 |
143 |
144 |
145 |
146 |
150 |
--------------------------------------------------------------------------------
/site/js/theme.js:
--------------------------------------------------------------------------------
1 | /* sphinx_rtd_theme version 0.4.1 | MIT license */
2 | /* Built 20180727 10:07 */
3 | require=function n(e,i,t){function o(s,a){if(!i[s]){if(!e[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(r)return r(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=i[s]={exports:{}};e[s][0].call(u.exports,function(n){var i=e[s][1][n];return o(i||n)},u,u.exports,n,e,i,t)}return i[s].exports}for(var r="function"==typeof require&&require,s=0;s"),n("table.docutils.footnote").wrap(""),n("table.docutils.citation").wrap(""),n(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var i=n(this);expand=n(''),expand.on("click",function(n){return e.toggleCurrent(i),n.stopPropagation(),!1}),i.prepend(expand)})},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),i=e.find('[href="'+n+'"]');if(0===i.length){var t=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(i=e.find('[href="#'+t.attr("id")+'"]')).length&&(i=e.find('[href="#"]'))}i.length>0&&($(".wy-menu-vertical .current").removeClass("current"),i.addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l1").parent().addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l2").addClass("current"),i.closest("li.toctree-l3").addClass("current"),i.closest("li.toctree-l4").addClass("current"))}catch(o){console.log("Error expanding nav for anchor",o)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,i=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(i),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],i=0;i
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | VICMATLAB
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
54 |
55 |
56 |
57 |
58 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | - Docs »
69 |
70 |
71 | -
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
Search Results
83 |
84 |
88 |
89 |
90 | Searching...
91 |
92 |
93 |
94 |
95 |
96 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/site/search/main.js:
--------------------------------------------------------------------------------
1 | function getSearchTermFromLocation() {
2 | var sPageURL = window.location.search.substring(1);
3 | var sURLVariables = sPageURL.split('&');
4 | for (var i = 0; i < sURLVariables.length; i++) {
5 | var sParameterName = sURLVariables[i].split('=');
6 | if (sParameterName[0] == 'q') {
7 | return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20'));
8 | }
9 | }
10 | }
11 |
12 | function joinUrl (base, path) {
13 | if (path.substring(0, 1) === "/") {
14 | // path starts with `/`. Thus it is absolute.
15 | return path;
16 | }
17 | if (base.substring(base.length-1) === "/") {
18 | // base ends with `/`
19 | return base + path;
20 | }
21 | return base + "/" + path;
22 | }
23 |
24 | function formatResult (location, title, summary) {
25 | return '' + summary +'
';
26 | }
27 |
28 | function displayResults (results) {
29 | var search_results = document.getElementById("mkdocs-search-results");
30 | while (search_results.firstChild) {
31 | search_results.removeChild(search_results.firstChild);
32 | }
33 | if (results.length > 0){
34 | for (var i=0; i < results.length; i++){
35 | var result = results[i];
36 | var html = formatResult(result.location, result.title, result.summary);
37 | search_results.insertAdjacentHTML('beforeend', html);
38 | }
39 | } else {
40 | search_results.insertAdjacentHTML('beforeend', "No results found
");
41 | }
42 | }
43 |
44 | function doSearch () {
45 | var query = document.getElementById('mkdocs-search-query').value;
46 | if (query.length > min_search_length) {
47 | if (!window.Worker) {
48 | displayResults(search(query));
49 | } else {
50 | searchWorker.postMessage({query: query});
51 | }
52 | } else {
53 | // Clear results for short queries
54 | displayResults([]);
55 | }
56 | }
57 |
58 | function initSearch () {
59 | var search_input = document.getElementById('mkdocs-search-query');
60 | if (search_input) {
61 | search_input.addEventListener("keyup", doSearch);
62 | }
63 | var term = getSearchTermFromLocation();
64 | if (term) {
65 | search_input.value = term;
66 | doSearch();
67 | }
68 | }
69 |
70 | function onWorkerMessage (e) {
71 | if (e.data.allowSearch) {
72 | initSearch();
73 | } else if (e.data.results) {
74 | var results = e.data.results;
75 | displayResults(results);
76 | } else if (e.data.config) {
77 | min_search_length = e.data.config.min_search_length-1;
78 | }
79 | }
80 |
81 | if (!window.Worker) {
82 | console.log('Web Worker API not supported');
83 | // load index in main thread
84 | $.getScript(joinUrl(base_url, "search/worker.js")).done(function () {
85 | console.log('Loaded worker');
86 | init();
87 | window.postMessage = function (msg) {
88 | onWorkerMessage({data: msg});
89 | };
90 | }).fail(function (jqxhr, settings, exception) {
91 | console.error('Could not load worker.js');
92 | });
93 | } else {
94 | // Wrap search in a web worker
95 | var searchWorker = new Worker(joinUrl(base_url, "search/worker.js"));
96 | searchWorker.postMessage({init: true});
97 | searchWorker.onmessage = onWorkerMessage;
98 | }
99 |
--------------------------------------------------------------------------------
/site/search/worker.js:
--------------------------------------------------------------------------------
1 | var base_path = 'function' === typeof importScripts ? '.' : '/search/';
2 | var allowSearch = false;
3 | var index;
4 | var documents = {};
5 | var lang = ['en'];
6 | var data;
7 |
8 | function getScript(script, callback) {
9 | console.log('Loading script: ' + script);
10 | $.getScript(base_path + script).done(function () {
11 | callback();
12 | }).fail(function (jqxhr, settings, exception) {
13 | console.log('Error: ' + exception);
14 | });
15 | }
16 |
17 | function getScriptsInOrder(scripts, callback) {
18 | if (scripts.length === 0) {
19 | callback();
20 | return;
21 | }
22 | getScript(scripts[0], function() {
23 | getScriptsInOrder(scripts.slice(1), callback);
24 | });
25 | }
26 |
27 | function loadScripts(urls, callback) {
28 | if( 'function' === typeof importScripts ) {
29 | importScripts.apply(null, urls);
30 | callback();
31 | } else {
32 | getScriptsInOrder(urls, callback);
33 | }
34 | }
35 |
36 | function onJSONLoaded () {
37 | data = JSON.parse(this.responseText);
38 | var scriptsToLoad = ['lunr.js'];
39 | if (data.config && data.config.lang && data.config.lang.length) {
40 | lang = data.config.lang;
41 | }
42 | if (lang.length > 1 || lang[0] !== "en") {
43 | scriptsToLoad.push('lunr.stemmer.support.js');
44 | if (lang.length > 1) {
45 | scriptsToLoad.push('lunr.multi.js');
46 | }
47 | for (var i=0; i < lang.length; i++) {
48 | if (lang[i] != 'en') {
49 | scriptsToLoad.push(['lunr', lang[i], 'js'].join('.'));
50 | }
51 | }
52 | }
53 | loadScripts(scriptsToLoad, onScriptsLoaded);
54 | }
55 |
56 | function onScriptsLoaded () {
57 | console.log('All search scripts loaded, building Lunr index...');
58 | if (data.config && data.config.separator && data.config.separator.length) {
59 | lunr.tokenizer.separator = new RegExp(data.config.separator);
60 | }
61 |
62 | if (data.index) {
63 | index = lunr.Index.load(data.index);
64 | data.docs.forEach(function (doc) {
65 | documents[doc.location] = doc;
66 | });
67 | console.log('Lunr pre-built index loaded, search ready');
68 | } else {
69 | index = lunr(function () {
70 | if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) {
71 | this.use(lunr[lang[0]]);
72 | } else if (lang.length > 1) {
73 | this.use(lunr.multiLanguage.apply(null, lang)); // spread operator not supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Browser_compatibility
74 | }
75 | this.field('title');
76 | this.field('text');
77 | this.ref('location');
78 |
79 | for (var i=0; i < data.docs.length; i++) {
80 | var doc = data.docs[i];
81 | this.add(doc);
82 | documents[doc.location] = doc;
83 | }
84 | });
85 | console.log('Lunr index built, search ready');
86 | }
87 | allowSearch = true;
88 | postMessage({config: data.config});
89 | postMessage({allowSearch: allowSearch});
90 | }
91 |
92 | function init () {
93 | var oReq = new XMLHttpRequest();
94 | oReq.addEventListener("load", onJSONLoaded);
95 | var index_path = base_path + '/search_index.json';
96 | if( 'function' === typeof importScripts ){
97 | index_path = 'search_index.json';
98 | }
99 | oReq.open("GET", index_path);
100 | oReq.send();
101 | }
102 |
103 | function search (query) {
104 | if (!allowSearch) {
105 | console.error('Assets for search still loading');
106 | return;
107 | }
108 |
109 | var resultDocuments = [];
110 | var results = index.search(query);
111 | for (var i=0; i < results.length; i++){
112 | var result = results[i];
113 | doc = documents[result.ref];
114 | doc.summary = doc.text.substring(0, 200);
115 | resultDocuments.push(doc);
116 | }
117 | return resultDocuments;
118 | }
119 |
120 | if( 'function' === typeof importScripts ) {
121 | onmessage = function (e) {
122 | if (e.data.init) {
123 | init();
124 | } else if (e.data.query) {
125 | postMessage({ results: search(e.data.query) });
126 | } else {
127 | console.error("Worker - Unrecognized message: " + e);
128 | }
129 | };
130 | }
131 |
--------------------------------------------------------------------------------
/site/sitemap.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | None
4 | 2020-07-20
5 | daily
6 |
7 | None
8 | 2020-07-20
9 | daily
10 |
11 |
--------------------------------------------------------------------------------
/site/sitemap.xml.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/site/sitemap.xml.gz
--------------------------------------------------------------------------------
/vicmatlab/forcings/aggregate_forcing.m:
--------------------------------------------------------------------------------
1 | % Aggregate forcing data
2 | %
3 | % Aggregates VIC meteorological forcing data from finer to coarser temporal
4 | % resolution
5 | %
6 | % Example
7 | % forcdir = '/media/jschap/HD_ExFAT/ucrb/disagg_forcings_L13';
8 | % delt_in = 1; % hours
9 | % delt_out = 24; % hours
10 | % starttime = datetime(1980, 1, 1, 0, 0, 0);
11 | % outdir = '/media/jschap/HD_ExFAT/ucrb/daily_forcings_L13';
12 | % precip_col = 1; % need to specify because precip is summed, not averaged,
13 | % to keep units consistant (mm/timestep)
14 | % hpc = 1; % to use parallel processing
15 |
16 | function [aggf, aggt] = aggregate_forcing(forcdir, delt_in, delt_out, starttime, outdir, precip_col, hpc)
17 |
18 | plotflag = 0;
19 |
20 | % Checks
21 | if mod(delt_out, delt_in) ~= 0
22 | error('delt_out must be a multiple of delt_in')
23 | end
24 |
25 | fnames = dir([forcdir '/full_data_*']);
26 | ncells = length(fnames);
27 | f = load(fullfile(forcdir, fnames(1).name));
28 |
29 | [nt_in, nvars] = size(f);
30 | nt_out = nt_in*delt_in/delt_out;
31 |
32 | % Returns error for now. Eventually should incorporate chopping as nec.
33 | if mod(nt_out, 1) ~= 0
34 | error('Non-integer number of output time steps. Need to chop or pad.')
35 | % Find the largest number<= nt_out that is evenly divisible by
36 | % delt_out/delt_in
37 | % floor(nt_out*delt_in/delt_out);
38 | end
39 |
40 | endtime = starttime + hours(delt_out)*nt_out - hours(delt_out);
41 | aggt = starttime:hours(delt_out):endtime;
42 |
43 | mkdir(outdir)
44 | disp(['Created directory to store outputs: ' outdir])
45 |
46 | if hpc == 1
47 | c = parcluster('local');
48 | nw = c.NumWorkers;
49 | parpool(nw-1)
50 | parfor k=1:ncells
51 | f = load(fullfile(forcdir, fnames(k).name));
52 | f_reshape = reshape(f, delt_out/delt_in, nt_out, nvars);
53 | aggf = squeeze(mean(f_reshape, 1));
54 | aggf(:, precip_col) = sum(f_reshape(:, :, precip_col), 1);
55 | if plotflag && k == 1
56 | figure
57 | plot(aggt, aggf(:, precip_col))
58 | xlabel('time')
59 | ylabel('precip')
60 | end
61 | dlmwrite(fullfile(outdir, fnames(k).name), aggf, ' ');
62 | end
63 | aggf = zeros(length(aggt),1);
64 | else
65 | for k=1:ncells
66 | f = load(fullfile(forcdir, fnames(k).name));
67 | f_reshape = reshape(f, delt_out/delt_in, nt_out, nvars);
68 | aggf = squeeze(mean(f_reshape, 1));
69 | aggf(:, precip_col) = sum(f_reshape(:, :, precip_col), 1);
70 | if plotflag && k == 1
71 | figure
72 | plot(aggt, aggf(:, precip_col))
73 | xlabel('time')
74 | ylabel('precip')
75 | end
76 | dlmwrite(fullfile(outdir, fnames(k).name), aggf, ' ');
77 | end
78 | end
79 |
80 | return
--------------------------------------------------------------------------------
/vicmatlab/forcings/load_ascii_forcings.m:
--------------------------------------------------------------------------------
1 | % Load ASCII Forcing Data
2 | %
3 | % Loads ASCII forcing data (e.g. for plotting)
4 | %
5 | % Dependencies: GetCoords.m
6 | % Updated 4/2/2020 JRS
7 | %
8 | % INPUTS
9 | % forcingpath = location of ASCII forcing files to plot
10 | % prefix
11 | % precision
12 | % varnames
13 | %
14 | % OUTPUTS
15 | % forc = structure array with information about the forcing data
16 | %
17 | % EXAMPLES
18 | % forcingpath = '/Users/jschapMac/Desktop/Tuolumne/Tuolumne8/Forcings/Disagg_Forc/';
19 | % forcingpath = '/Volumes/HD3/SWOTDA/Data/IRB/VIC/MiniDomain2/aligned_forcings';
20 | % forcingpath = '/Volumes/HD4/SWOTDA/Data/Tuolumne/forc_ascii';
21 | % forcingpath = '/Volumes/HD3/SWOTDA/Data/IRB/VIC/MiniDomain2/2018-2018_forc_lasttest';
22 | %
23 | % Sample arguments
24 | % forcingpath = './data/forc_2009-2011';
25 | % precision = 5;
26 | % varnames = {'PRECIP','TMIN','TMAX','WIND'};
27 | % prefix = 'data_';
28 |
29 | function forc = load_ascii_forcings(forcingpath, prefix, precision, varnames)
30 |
31 | %% Load forcing data
32 |
33 | forcenames = dir(fullfile(forcingpath, [prefix '*']));
34 | ncells = length(forcenames);
35 | tmpforc = dlmread(fullfile(forcingpath, forcenames(1).name));
36 |
37 | nsteps = size(tmpforc,1);
38 | nvars = size(tmpforc,2);
39 |
40 | % Adapted from LoadVICResults
41 | gridcells = cell(ncells, 1);
42 | for k=1:ncells
43 | tmpstring = forcenames(k).name;
44 | % tmpstring = strrep(tmpstring,'-',''); % remove some characters bc Matlab cannot handle them
45 | tmpstring = strrep(tmpstring,'.','_');
46 | gridcells{k} = tmpstring;
47 | end
48 |
49 | [lat, lon] = GetCoords(gridcells, precision, prefix);
50 |
51 | %% Read in data for all grid cells and times (OK for a relatively small domain)
52 |
53 | % This is definitely not going to work for a large domain
54 | % Going to have to break it up
55 | % Check if the domain is "large"
56 |
57 | if ncells > 500
58 | disp('Relatively large study area')
59 | disp('Use make_netcdf_forcing()')
60 | error('Study area is too big. It will fill up RAM')
61 | % disp('Loading daily average forcing data')
62 | %
63 | % % Using a matfile to deal with the memory issue
64 | % matOjb = matfile('./precipitation.mat');
65 | %
66 | % ncells = 10;
67 | % % precip = NaN(nsteps, ncells);
68 | %
69 | % for k=1:ncells
70 | % forc_current = dlmread(fullfile(forcingpath, forcenames(k).name));
71 | %
72 | % precip = forc_current(:,1);
73 | %
74 | % if k==1
75 | % save('./precip.m', 'precip', '-v7.3')
76 | % m = matfile('./precip.m', 'Writable', true);
77 | % else
78 | % m.precip(:,k) = forc_current;
79 | % end
80 | %
81 | % end
82 |
83 | else
84 | disp('Relatively small study area')
85 | disp('Loading all forcing data')
86 | FORC = NaN(nsteps, nvars, ncells);
87 | disp(['There are ' num2str(nvars) ' variables in the forcing files']);
88 | for k=1:ncells
89 | FORC(:,:,k) = dlmread(fullfile(forcingpath, forcenames(k).name));
90 | end
91 | end
92 |
93 |
94 | %% Put forcing data into a nice structure
95 |
96 | forc = struct();
97 | forc.names = varnames;
98 | for i=1:length(varnames)
99 | forc.(varnames{i}) = squeeze(FORC(:,i,:));
100 | end
101 | forc.dimensions = {'timestep','gridcell'};
102 | forc.lon = lon;
103 | forc.lat = lat;
104 |
105 | end
106 |
--------------------------------------------------------------------------------
/vicmatlab/forcings/save_forcings.m:
--------------------------------------------------------------------------------
1 | % Save Forcings
2 | %
3 | % 4/2/2020 JRS
4 | % A function to save the outputs of subset_forcings
5 |
6 | function save_forcings(metlat, lat_ind, metlon, lon_ind, force_out, data_cum, grid_decimal)
7 |
8 | ncells = length(lat_ind);
9 | fstring = ['%.' num2str(grid_decimal) 'f'];
10 | for k=1:ncells
11 | filename = ['data_' num2str(metlat(lat_ind(k)),fstring) '_' num2str(metlon(lon_ind(k)),fstring)];
12 | dlmwrite(fullfile(force_out, filename), data_cum(:,:,k), ' ')
13 | end
14 | disp(['Forcing data saved to ' force_out])
15 |
16 | end
--------------------------------------------------------------------------------
/vicmatlab/forcings/subset_forcings.m:
--------------------------------------------------------------------------------
1 | % Subsets forcings to a particular basin
2 | %
3 | % Written 3/9/2020 JRS
4 | %
5 | % Supercedes subset_forcings
6 | % Code has been modified to use MUCH less RAM
7 | %
8 | % Default values for optional arguments
9 | % numforcings = 4;
10 | % grid_decimal = 5;
11 | % has_lots_of_ram = 0;
12 | %
13 | % Requires PREC, TMIN, TMAX, WIND forcings in NetCDF files, one per year
14 |
15 | function data_cum = subset_forcings(indir, outdir, beginyear, endyear, maskname, varargin)
16 |
17 | % Set default values for optional arguments
18 |
19 | numvarargs = length(varargin);
20 | if numvarargs > 3
21 | error('subset_forcings requires at most three optional inputs');
22 | end
23 |
24 | optargs = {4, 5, 0};
25 | optargs(1:numvarargs) = varargin;
26 |
27 | [numforcings, grid_decimal, has_lots_of_ram] = optargs{:};
28 |
29 | mkdir(outdir)
30 | disp(['Created directory ', outdir, ' for outputs']);
31 |
32 | % Load basin mask
33 | [basin_mask, ~, lon, lat] = geotiffread2(maskname);
34 |
35 | if isa(basin_mask, 'single')
36 | disp('basin mask is single')
37 | disp('converting zeros to nans for subsetting')
38 | basin_mask = double(basin_mask);
39 | basin_mask(basin_mask==0) = NaN;
40 | end
41 |
42 | [mask_lonv, mask_latv, ~] = grid2xyz(lon', lat', basin_mask);
43 | ncells = length(mask_lonv);
44 |
45 | % Identify grid cells to keep
46 | metlat = ncread(fullfile(indir, ['prec.' num2str(beginyear) '.nc']), 'lat');
47 | metlon = ncread(fullfile(indir, ['prec.' num2str(endyear) '.nc']), 'lon');
48 | metlon = metlon - 360;
49 |
50 | lat_ind = zeros(ncells,1);
51 | lon_ind = zeros(ncells,1);
52 | for k=1:ncells
53 | [~, lat_ind(k)] = min(abs(mask_latv(k) - metlat));
54 | [~, lon_ind(k)] = min(abs(mask_lonv(k) - metlon));
55 | end
56 |
57 | %% Extract forcing variables
58 |
59 | disp('Extracting forcing variables')
60 |
61 | nyears = endyear - beginyear + 1;
62 | t_ind = 1;
63 | cum_days = 0;
64 |
65 | for t = beginyear:endyear
66 |
67 | if t==beginyear, tic; end
68 |
69 | prec = ncread(fullfile(indir, ['prec.' num2str(t) '.nc']), 'prec');
70 | tmax = ncread(fullfile(indir, ['tmax.' num2str(t) '.nc']), 'tmax');
71 | tmin = ncread(fullfile(indir, ['tmin.' num2str(t) '.nc']), 'tmin');
72 | wind = ncread(fullfile(indir, ['wind.' num2str(t) '.nc']), 'wind');
73 | % each of these arrays requires about 1.2 GB of storage
74 |
75 | prec = permute(prec, [2,1,3]);
76 | tmax = permute(tmax, [2,1,3]);
77 | tmin = permute(tmin, [2,1,3]);
78 | wind = permute(wind, [2,1,3]);
79 |
80 | % test plot to check the data were loaded properly
81 | % tmax_map = tmax(:,:,1);
82 | % figure
83 | % plotraster([min(metlon) max(metlon)], [min(metlat) max(metlat)], tmax_map, 'tmax', 'Lon','Lat')
84 |
85 | info = ncinfo(fullfile(indir, ['prec.' num2str(t) '.nc']));
86 | ndays = info.Dimensions(1).Length; % get number of days in the year
87 | data = NaN(ndays, numforcings, ncells);
88 |
89 | for k=1:ncells
90 | data(:,1,k) = prec(lat_ind(k),lon_ind(k), :);
91 | data(:,2,k) = tmin(lat_ind(k),lon_ind(k), :);
92 | data(:,3,k) = tmax(lat_ind(k),lon_ind(k), :);
93 | data(:,4,k) = wind(lat_ind(k),lon_ind(k), :);
94 | end
95 |
96 | % data_cum grows on each loop iteration
97 | % unless the computer has a ton of RAM, this is going to get out of
98 | % hand, so there is an option to save the data to disk and read it back
99 | % in, in a separate step
100 |
101 | if has_lots_of_ram
102 | cum_days = size(prec,3) + cum_days;
103 | if t_ind~=1
104 | data_cum = vertcat(data_cum, data);
105 | else
106 | data_cum = data;
107 | end
108 | else
109 | disp('save this year''s processed data to file')
110 |
111 | savename = fullfile(outdir, ['clipped_forcing_data_year_' num2str(t) '.mat']);
112 | save(savename, 'data');
113 |
114 | cum_days = size(prec,3) + cum_days;
115 | clearvars('prec','tmax','tmin','wind');
116 | end
117 |
118 | t_ind = t_ind + 1;
119 |
120 | if t==beginyear
121 | disp(['About ' num2str(toc*nyears/60) ' minutes remaining.'])
122 | end
123 | disp(['Finished processing year ' num2str(t)])
124 |
125 | end
126 |
127 |
128 | %% Combine forcings together, if necessary
129 | if ~has_lots_of_ram
130 | t_ind = 1;
131 | for t=beginyear:endyear
132 | savename = fullfile(outdir, ['clipped_forcing_data_year_' num2str(t) '.mat']);
133 | load(savename, 'data');
134 | if t_ind==1
135 | data_cum = data;
136 | else
137 | data_cum = vertcat(data_cum, data);
138 | end
139 | t_ind = t_ind + 1;
140 | end
141 | end
142 |
143 | %% Save clipped met. forcings
144 | save_forcings(metlat, lat_ind, metlon, lon_ind, outdir, data_cum, grid_decimal);
145 |
146 | end
147 |
148 |
149 | % fstring = ['%.' num2str(grid_decimal) 'f'];
150 | % for k=1:ncells
151 | % filename = ['data_' num2str(metlat(lat_ind(k)),fstring) '_' num2str(metlon(lon_ind(k)),fstring)];
152 | % dlmwrite(fullfile(force_out, filename), data_cum(:,:,k), ' ')
153 | % end
154 | % disp(['Forcing data saved to ' force_out])
--------------------------------------------------------------------------------
/vicmatlab/forcings/subset_forcings_time.m:
--------------------------------------------------------------------------------
1 | % Subset forcings (in time)
2 | %
3 | % start_date = initial time for input forcings
4 | % t0 = initial time for subsetting
5 | % tf = final time for subsetting
6 |
7 | function subset_forcings_time(indir, outdir, start_date, t0, tf, prefix, time_step)
8 |
9 | mkdir(outdir)
10 | disp(['Created directory ', outdir, ' for outputs']);
11 |
12 | %% Subset
13 |
14 | forcnames = dir([fullfile(indir, prefix) '*']);
15 |
16 | origfile = fullfile(indir, forcnames(1).name);
17 | forc = load(origfile);
18 | [nt, ~] = size(forc);
19 | ncells = length(forcnames);
20 | dt = hours(time_step);
21 | date_vect = start_date:dt:(start_date + (nt-1)*dt);
22 | date_vect = date_vect';
23 | [~,start_ind] = ismember(t0, date_vect);
24 | [~,end_ind] = ismember(tf, date_vect);
25 |
26 | for k=1:ncells
27 | origfile = fullfile(indir, forcnames(k).name);
28 | forc = load(origfile);
29 | newforc = forc(start_ind:end_ind,:);
30 | dlmwrite(fullfile(outdir, forcnames(k).name), newforc, ' ');
31 | end
32 |
33 | end
34 |
--------------------------------------------------------------------------------
/vicmatlab/forcings/subset_forcings_to_spf.m:
--------------------------------------------------------------------------------
1 | % Subset forcings
2 | %
3 | % Copy over ASCII forcings for a particular basin
4 | %
5 | % Example:
6 | % subset_forcings(soilfile, forcdir, 'Forcings_')
7 | % soilfile = '/Volumes/HD3/SWOTDA/Calibration/Bhakra/soils_bhakra.txt';
8 | % prefix = 'Forcings_';
9 | % forcdir = '/Volumes/HD4/SWOTDA/Data/IRB/Downscaled_Forcings/ascii_1980-2019';
10 | % newforcdir = '/Volumes/HD4/SWOTDA/Data/IRB/ascii_1980-2019';
11 |
12 | function [soil_lon, soil_lat] = subset_forcings_to_spf(soilfile, forcdir, prefix, newforcdir)
13 |
14 | mkdir(newforcdir)
15 |
16 | soils = load(soilfile);
17 | forcnames = dir([fullfile(forcdir, prefix) '*']);
18 |
19 | [lon, lat] = get_coordinates_from_VIC_file(forcdir, prefix);
20 |
21 | soil_lat = soils(:,3);
22 | soil_lon = soils(:,4);
23 |
24 | ncells = length(soil_lat);
25 | T = delaunayn([lat, lon]);
26 | disp(['There are ' num2str(ncells) ' grid cells'])
27 | for j=1:ncells
28 | k = dsearchn([lat, lon],T,[soil_lat(j) soil_lon(j)]);
29 | origfile = fullfile(forcdir, forcnames(k).name);
30 | newfile = fullfile(newforcdir, forcnames(k).name);
31 | copyfile(origfile, newfile);
32 | if mod(j,100)==0
33 | disp(num2str(j))
34 | end
35 | end
36 |
37 | return
38 |
--------------------------------------------------------------------------------
/vicmatlab/forcings/upscale_forcing.m:
--------------------------------------------------------------------------------
1 | % Upscale forcing
2 | %
3 | % Upscales forcing data from one resolution to another
4 |
5 | function upscale_forcing(forcdir, prefix, newres, oldres)
6 |
7 | [lon, lat] = get_coordinates_from_VIC_file(forcdir, prefix);
8 |
9 |
10 |
11 | lat = newsoils(:,3);
12 | lon = newsoils(:,4);
13 | f = newres/oldres;
14 |
15 | % Upscale similar to upscale_vegpars or upscale_soils
16 |
17 | runcell = xyz2grid(lon, lat, oldsoils(:,1));
18 | [m1, n1] = size(runcell); % original dimensions
19 |
20 | % new dimensions
21 | m2 = m1/f;
22 | n2 = floor(n1/f);
23 |
24 | % Upscale (or downscale) (method from Walter Roberson in MATLAB Answers)
25 | minlat = min(lat);
26 | maxlat = max(lat);
27 | minlon = min(lon);
28 | maxlon = max(lon);
29 | oldlats = linspace(minlat, maxlat, m1);
30 | oldlons = linspace(minlon, maxlon, n1)';
31 | newlats = linspace(minlat, maxlat, m2);
32 | newlons = linspace(minlon, maxlon, n2)'; % resolution is a couple hundred meters off....
33 |
34 | runcell2 = interp2(oldlats, oldlons, runcell', newlats, newlons, 'linear');
35 | runcell2 = runcell2';
36 | runcell2(isnan(runcell2))=0;
37 | runcell3 = runcell2(:); % indexing
38 |
39 | return
--------------------------------------------------------------------------------
/vicmatlab/general/check_water_year.m:
--------------------------------------------------------------------------------
1 | function [tv_out, var_out] = check_water_year(timevector, var_in)
2 |
3 | needs_clipping = 0;
4 |
5 | % Check to make sure the inputs are on a water-year basis
6 | if month(timevector(1)) ~= 10 || day(timevector(1)) ~= 1
7 | disp('Must be on a water year basis')
8 | disp('First day is not Oct. 1. Clipping.')
9 | needs_clipping = 1;
10 | end
11 |
12 | if month(timevector(end)) ~= 9 || day(timevector(end)) ~= 30
13 | disp('Must be on a water year basis')
14 | disp('Last day is not Sept. 30. Clipping.')
15 | needs_clipping = 1;
16 | end
17 |
18 | if needs_clipping
19 |
20 | t1 = find(month(timevector) == 10 & day(timevector)==1);
21 | t2 = find(month(timevector) == 9 & day(timevector)==30);
22 | t_first = t1(1);
23 | t_last = t2(end);
24 |
25 | tv_out = timevector(t_first:t_last);
26 | var_out = var_in(t_first:t_last);
27 |
28 | else
29 | % no clipping needed
30 | tv_out = timevector;
31 | var_out = var_in;
32 | end
33 |
34 | return
--------------------------------------------------------------------------------
/vicmatlab/general/georefobj2mat.m:
--------------------------------------------------------------------------------
1 | % Georeferencing object to georeferencing matrix
2 | %
3 | % Written for latlon coordinates
4 | %
5 | % INPUTS
6 | % R = georeferencing object
7 | % type = "LL" or "center"
8 |
9 | function Rmat = georefobj2mat(R, type)
10 |
11 | xres = R.CellExtentInLongitude;
12 | yres = R.CellExtentInLatitude;
13 |
14 | switch type
15 | case 'LL'
16 | xmin = R.LongitudeLimits(1) + xres/2;
17 | ymin = R.LatitudeLimits(1) + yres/2;
18 | case 'center'
19 | xmin = R.LongitudeLimits(1);
20 | ymin = R.LatitudeLimits(1);
21 | otherwise
22 | disp('Please provide information about raster format')
23 | end
24 |
25 | Rmat = makerefmat(xmin, ymin, xres, yres);
26 |
27 |
28 | return
--------------------------------------------------------------------------------
/vicmatlab/general/geotiffread2.m:
--------------------------------------------------------------------------------
1 | % Geotiffread2
2 | %
3 | % Modified version of geotiffread that returns lat and lon coordinates
4 |
5 | function [A, R, lon, lat] = geotiffread2(fname)
6 |
7 | try
8 | [A, ~, R] = geotiffread(fname);
9 | A = flipud(A);
10 | Rmat = georefobj2mat(R, 'LL');
11 | catch
12 | [A, R] = geotiffread(fname);
13 | A = flipud(A);
14 | Rmat = georefobj2mat(R, 'LL');
15 | end
16 |
17 | [lon, lat] = pixcenters(Rmat, size(A));
18 |
19 | % Remove no data values
20 | A(A < -1000) = NaN;
21 |
22 | return
--------------------------------------------------------------------------------
/vicmatlab/general/grid2xyz.m:
--------------------------------------------------------------------------------
1 | function [x,y,z] = grid2xyz(Xgrid, Ygrid, Zgrid)
2 | %GRID2XYZ converts a grid to xyz and removes NaN's
3 | %
4 | % Syntax:
5 | % [x,y,z] = grid2xyz(Xgrid, Ygrid, Zgrid)
6 | %
7 | % Input:
8 | % Xgrid = x grid coordinates
9 | % Ygrid = y grid coordinates
10 | % Zgrid = z grid coordinates
11 | %
12 | % Output:
13 | % x = x coordinate (vector)
14 | % y = y coordinate (vector)
15 | % z = z coordinate (vector)
16 | %
17 | % Example
18 | % [x,y,z] = grid2xyz(Xgrid, Ygrid, Zgrid)
19 | %
20 | % See also
21 |
22 | %% Copyright notice
23 | % --------------------------------------------------------------------
24 | % Copyright (C) 2010 Alkyon Hydraulic Consultancy & Research
25 | % grasmeijerb
26 | %
27 | % bart.grasmeijer@alkyon.nl
28 | %
29 | % P.O. Box 248
30 | % 8300 AE Emmeloord
31 | % The Netherlands
32 | %
33 | % This library is free software: you can redistribute it and/or
34 | % modify it under the terms of the GNU Lesser General Public
35 | % License as published by the Free Software Foundation, either
36 | % version 2.1 of the License, or (at your option) any later version.
37 | %
38 | % This library is distributed in the hope that it will be useful,
39 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
40 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41 | % Lesser General Public License for more details.
42 | %
43 | % You should have received a copy of the GNU Lesser General Public
44 | % License along with this library. If not, see .
45 | % --------------------------------------------------------------------
46 |
47 | % This tool is part of OpenEarthTools.
48 | % OpenEarthTools is an online collaboration to share and manage data and
49 | % programming tools in an open source, version controlled environment.
50 | % Sign up to recieve regular updates of this function, and to contribute
51 | % your own tools.
52 |
53 | %% Version
54 | % Created: 05 Jul 2010
55 | % Created with Matlab version: 7.10.0.499 (R2010a)
56 |
57 | % $Id$
58 | % $Date$
59 | % $Author$
60 | % $Revision$
61 | % $HeadURL$
62 | % $Keywords: $
63 |
64 | %%
65 |
66 |
67 | %%%%%%%
68 | % modified by Jacob Schaperow to take a slightly different input
69 | if size(Xgrid,2) == 1
70 | [Xgrid, Ygrid] = meshgrid(Xgrid, Ygrid);
71 | end
72 | %%%%%%%
73 |
74 | x = reshape(Xgrid,[numel(Xgrid),1]);
75 | y = reshape(Ygrid,[numel(Ygrid),1]);
76 | z = reshape(Zgrid,[numel(Zgrid),1]);
77 | mynans = isnan(x) | isnan(y) | isnan(z);
78 | x(mynans) = [];
79 | y(mynans) = [];
80 | z(mynans) = [];
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/vicmatlab/general/plotraster.m:
--------------------------------------------------------------------------------
1 | % Plot Raster
2 | %
3 | % Revised 4/4/2020 JRS
4 | %
5 | % Optional arguments (and defaults):
6 | % xtext = 'Lon'
7 | % ytext = 'Lat'
8 | % inan = 1
9 | % fontsize = 18
10 | % target_axis = gca
11 | %
12 | % Usage
13 | % plotraster(x, y, r, title, xlab, ylab, inan, fontsize, target_axis)
14 | % plotraster(x,y,r,title, xlab, ylab, inan)
15 | % plotraster(x,y,r,title)
16 |
17 | function im = plotraster(x, y, r, titletext, varargin)
18 |
19 | numvarargs = length(varargin);
20 | if numvarargs > 5
21 | error('The max number of optional arguments is 5')
22 | end
23 |
24 | optargs = {'Lon', 'Lat', 1, 18, gca};
25 | optargs(1:numvarargs) = varargin;
26 | [xtext, ytext, inan, fontsize, target_axis] = optargs{:};
27 |
28 | if length(x) > 2
29 | xx = zeros(2,1);
30 | xx(1) = min(x);
31 | xx(2) = max(x);
32 | x = xx;
33 | end
34 |
35 | if length(y) > 2
36 | yy = zeros(2,1);
37 | yy(1) = min(y);
38 | yy(2) = max(y);
39 | y = yy;
40 | end
41 |
42 | % inan = 1;
43 | if inan
44 | im = imagescnan(x,y,r, 'Parent', target_axis);
45 | else
46 | im = imagesc(x, y, r, 'Parent', target_axis);
47 | end
48 |
49 | title(target_axis, titletext)
50 | xlabel(target_axis, xtext)
51 | ylabel(target_axis, ytext)
52 |
53 | % cmap = colormap;
54 | % cmap(1,:) = [1,1,1];
55 | % colormap(cmap);
56 | colorbar(target_axis);
57 | %
58 |
59 | set(target_axis, 'ydir', 'normal')
60 | set(target_axis, 'fontsize', fontsize)
61 |
62 | return
--------------------------------------------------------------------------------
/vicmatlab/general/xyz2grid.m:
--------------------------------------------------------------------------------
1 | % Note: I have modified one line of this code (flipping the output
2 | % upside-down) -JRS
3 | %
4 | %
5 |
6 | function varargout = xyz2grid(varargin)
7 | % xyz2grid converts regularly-spaced columnated x,y,z data into gridded data.
8 | %
9 | %% Syntax
10 | %
11 | % Z = xyz2grid(x,y,z)
12 | % Z = xyz2grid(filename)
13 | % Z = xyz2grid(filename,Name,Value)
14 | % [X,Y,Z] = xyz2grid(...)
15 | %
16 | %% Description
17 | %
18 | % Z = xyz2grid(x,y,z) assumes x and y have some form of regularity and puts
19 | % the corresponding values of z into a regular 2D MxN gridded matrix Z.
20 | %
21 | % Z = xyz2grid(filename) loads data from a .xyz file of three columns
22 | % (x, y, and z) then puts the data into a grid. This function assumes the
23 | % input x,y,z data have some gridded regularity, but may have some missing
24 | % data points.
25 | %
26 | % Z = xyz2grid(filename,Name,Value) opens a .xyz file with any textscan
27 | % options Name,Value, for example, 'headerlines',1.
28 | %
29 | % [X,Y,Z] = xyz2grid(...) returns 2D meshgridded X and Y matrices corresponding
30 | % to the values in Z.
31 | %
32 | %% Example
33 | % You may have some columns of x,y, and z values that look like this:
34 | %
35 | % x = [1 1 2 2 2 3 3];
36 | % y = [1 2 1 2 3 1 3];
37 | % z = [1 2 4 5 6 7 9];
38 | %
39 | % scatter(x,y,500,z,'filled')
40 | % axis([0 4 0 4])
41 | % colorbar
42 | %
43 | % From the scatter plot above, you can see that there is some gridded
44 | % regularity to the data, even though a couple of spots in the grid
45 | % are missing. That's okay. Let's grid it up:
46 | %
47 | % [X,Y,Z] = xyz2grid(x,y,z)
48 | % X =
49 | % 1 2 3
50 | % 1 2 3
51 | % 1 2 3
52 | % Y =
53 | % 3 3 3
54 | % 2 2 2
55 | % 1 1 1
56 | % Z =
57 | % NaN 6 9
58 | % 2 5 NaN
59 | % 1 4 7
60 | %
61 | %% Author Info
62 | % This script was written by Chad A. Greene of the University of Texas
63 | % at Austin's Institute for Geophysics (UTIG), April 2016.
64 | % http://www.chadagreene.com
65 | %
66 | % See also xyzread and accumarray.
67 |
68 | %% Error checks and input parsing:
69 |
70 | narginchk(1,inf)
71 |
72 | % Has the user input x,y,z coordinates or a .xyz filename? Assume filename if first input is a string:
73 | if isnumeric(varargin{1})
74 | x = varargin{1};
75 | y = varargin{2};
76 | z = varargin{3};
77 | else
78 | [x,y,z] = xyzread(varargin{:});
79 | end
80 |
81 | assert(isequal(size(x),size(y),size(z))==1,'Dimensions of x,y, and z must match.')
82 | assert(isvector(x)==1,'Inputs x,y, and z must be vectors.')
83 |
84 | %% Grid xyz:
85 |
86 | % Get unique values of x and y:
87 | [xs,~,xi] = unique(x(:),'sorted');
88 | [ys,~,yi] = unique(y(:),'sorted');
89 |
90 | % Before we go any further, we better make sure we're not gridding scattered data.
91 | % This is not a perfect assessor, but it's at least some kind of check:
92 | if numel(xs)==numel(z)
93 | warning 'It does not seem like the xyz dataset is gridded. You may be attempting to grid scattered data, but I will try to put it into a 2D matrix anyway. Check the output spacing of X and Y.';
94 | end
95 |
96 | % Sum up all the Z values that in each x,y grid point:
97 | Z = accumarray([yi xi],z(:),[],[],NaN);
98 |
99 | % ------------------------------------------------------------------------
100 | % ------------------------------------------------------------------------
101 | % ------------------------------------------------------------------------
102 | % Flip Z to match X,Y and to be correctly oriented in ij image coordinates:
103 | % Z = flipud(Z); % commented out 8/8/2019 JRS
104 | % ------------------------------------------------------------------------
105 | % ------------------------------------------------------------------------
106 | % ------------------------------------------------------------------------
107 |
108 | %% Package up the outputs:
109 |
110 | switch nargout
111 | case 1
112 | varargout{1} = Z;
113 |
114 | case 3
115 |
116 | % Create a meshgrid of x and y:
117 | [varargout{1},varargout{2}] = meshgrid(xs,flipud(ys));
118 | varargout{3} = Z;
119 |
120 | otherwise
121 | error('Wrong number of outputs.')
122 | end
123 |
124 |
125 | end
--------------------------------------------------------------------------------
/vicmatlab/outputs/annual_average.m:
--------------------------------------------------------------------------------
1 | % Annual average
2 | %
3 | % Calculates the annual average values (on a water-year basis) of the input
4 | % variable, which should be input as a time series
5 |
6 | function [t_out, var_out] = annual_average(timevector, var, category)
7 |
8 | %% Input checking
9 |
10 | % If the inputs are not on a water-year basis, do something to ensure they
11 | % are. Try clipping off the ends.
12 | [timevector, var] = check_water_year(timevector, var);
13 |
14 | %% Calculate the average
15 |
16 | t_out = unique(year(timevector));
17 | t_out = t_out(2:end);
18 | nyears = length(t_out);
19 |
20 | t1 = find(month(timevector) == 10 & day(timevector)==1);
21 | t2 = find(month(timevector) == 9 & day(timevector)==30);
22 |
23 | var_out = zeros(nyears, 1);
24 | for t=1:nyears
25 |
26 | switch category
27 | case 'flux'
28 | var_out(t) = sum(var(t1(t):t2(t)));
29 | case 'store'
30 | var_out(t) = mean(var(t1(t):t2(t)));
31 | end
32 |
33 | end
34 |
35 | return
--------------------------------------------------------------------------------
/vicmatlab/outputs/calc_basin_avg_ts.m:
--------------------------------------------------------------------------------
1 | % Basin average time series
2 | %
3 | % An accurate way to calculate basin-average time series from a time series
4 | % of basin maps
5 |
6 | function ts = calc_basin_avg_ts(mapts, calcsum)
7 |
8 | [nlon, nlat, nt] = size(mapts);
9 |
10 | temporary = reshape(mapts, nlon*nlat, nt);
11 | ts = nanmean(temporary, 1)'; % This method calculates the average totally accurately...
12 |
13 | if calcsum
14 | ts = nansum(temporary,1)';
15 | end
16 |
17 | return
--------------------------------------------------------------------------------
/vicmatlab/outputs/calc_summed_QdQb.m:
--------------------------------------------------------------------------------
1 | % Calculate summed runoff and baseflow
2 | %
3 | % wbdir = directory containing water balance output files
4 | % I've checked this code pretty thoroughly. I'm convinced it gives answers
5 | % in the correct units - 8/10/2020 JRS
6 | %
7 | % Validated with the Yampa basin model - 8/12/2020 JRS
8 |
9 | function [sQ, sQd, sQb, timevector] = calc_summed_QdQb(wbdir, prefix, A_basin, varargin)
10 |
11 | numvarargs = length(varargin);
12 | if numvarargs > 2
13 | error('The max number of optional arguments is 5')
14 | end
15 |
16 | optargs = {6, 7};
17 | optargs(1:numvarargs) = varargin;
18 | [runoff_col, baseflow_col] = optargs{:};
19 |
20 | if runoff_col == 6 && baseflow_col == 7
21 | disp('Assuming runoff and baseflow are in columns 6 and 7 of outputs')
22 | end
23 |
24 | fnames = dir([wbdir '/' prefix '*']);
25 |
26 | if strcmp(fnames(1).name(end-3:end), '.txt')
27 | ncells = length(fnames);
28 | dat = readmatrix(fullfile(wbdir,fnames(1).name));
29 | timevector = datetime(dat(:,1), dat(:,2), dat(:,3));
30 | nt = length(timevector);
31 | Qb = zeros(nt,ncells);
32 | Qd = zeros(nt,ncells);
33 | for k=1:ncells
34 | dat = readmatrix(fullfile(wbdir, fnames(k).name));
35 | Qb(:,k) = dat(:,baseflow_col); % baseflow
36 | Qd(:,k) = dat(:,runoff_col); % runoff
37 | end
38 | else
39 | ncells = length(fnames);
40 | dat = dlmread(fullfile(wbdir,fnames(1).name));
41 | timevector = datetime(dat(:,1), dat(:,2), dat(:,3));
42 | nt = length(timevector);
43 | Qb = zeros(nt,ncells);
44 | Qd = zeros(nt,ncells);
45 | for k=1:ncells
46 | dat = dlmread(fullfile(wbdir, fnames(k).name));
47 | Qb(:,k) = dat(:,baseflow_col); % baseflow
48 | Qd(:,k) = dat(:,runoff_col); % runoff
49 | end
50 | end
51 |
52 | % Convert from mm/day to m^3/s
53 | % ncells = 7833;
54 | A_cell = A_basin/ncells; % km^2, average grid cell area
55 | conversion_factor = A_cell*1000/(24*3600);
56 | Qb = Qb.*conversion_factor; % m^3/s for each grid cell
57 | Qd = Qd.*conversion_factor; % m^3/s for each grid cell
58 |
59 | sQb = sum(Qb,2);
60 | sQd = sum(Qd,2);
61 | sQ = sQb + sQd;
62 |
63 | % [tm, Qm] = daily_to_monthly(timevector, sQ, 'mean')
64 |
65 | return
--------------------------------------------------------------------------------
/vicmatlab/outputs/get_vic_run_metadata.m:
--------------------------------------------------------------------------------
1 | % Get VIC run metadata
2 | %
3 | % Gets metadata from the VIC run, such as simulation start and end times,
4 | % names of output variables, etc.
5 | %
6 | % Inputs
7 | % wb_out_dir
8 | % eb_out_dir
9 | % timestep_out = 'daily' or 'hourly'
10 | % savename = optional savename. Use [] if not saving.
11 |
12 | function info = get_vic_run_metadata(vic_out_dir, timestep_out)
13 |
14 | headerlines = 3;
15 |
16 | wb_out_dir = fullfile(vic_out_dir, 'wb');
17 | eb_out_dir = fullfile(vic_out_dir, 'eb');
18 |
19 | % check that the VIC output files have been organized properly into /wb/
20 | % and /eb/ folders
21 | if exist(wb_out_dir, 'dir') == 0
22 | error('Make sure the VIC output files have been organized properly')
23 | end
24 |
25 | % Get metadata (lat, lon, time, names)
26 | wbnames = dir(fullfile(wb_out_dir, 'wb*'));
27 | ebnames = dir(fullfile(eb_out_dir, 'eb*'));
28 |
29 | % [lon, lat] = get_coordinates_from_VIC_file(wb_out_dir, 'wb', 'fluxes');
30 | [lon, lat] = get_coordinates_from_VIC_file(wb_out_dir, 'wb_');
31 |
32 | sample_wb_file = fullfile(wb_out_dir, wbnames(1).name);
33 | sample_eb_file = fullfile(eb_out_dir, ebnames(1).name);
34 | wb_varnames = get_vic_header(sample_wb_file, headerlines);
35 | eb_varnames = get_vic_header(sample_eb_file, headerlines);
36 |
37 | eb_out = dlmread(sample_eb_file, '\t', headerlines, 0);
38 | switch timestep_out
39 | case 'hourly'
40 | date_array = eb_out(:,1:4);
41 | timevector = datetime(date_array(:,1), date_array(:,2), date_array(:,3), 0, 0, date_array(:,4));
42 | case 'daily'
43 | date_array = eb_out(:,1:3);
44 | timevector = datetime(date_array(:,1), date_array(:,2), date_array(:,3));
45 | end
46 |
47 | info.time = timevector;
48 | info.wbvars = wb_varnames;
49 | info.ebvars = eb_varnames;
50 | info.ncells = length(wbnames);
51 | info.nt = length(timevector);
52 | info.wb_out_dir = wb_out_dir;
53 | info.eb_out_dir = eb_out_dir;
54 | info.headerlines = headerlines;
55 |
56 | info.lon = lon;
57 | info.lat = lat;
58 | % info.lon = flipud(lon);
59 | % info.lat = flipud(lat); % should be in decreasing order
60 | % check_latlon(info.lat, info.lon);
61 |
62 | return
63 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/get_vic_run_metadata2.m:
--------------------------------------------------------------------------------
1 | % Get VIC run metadata
2 | %
3 | % Gets metadata from the VIC run, such as simulation start and end times,
4 | % names of output variables, etc.
5 | %
6 | % Inputs
7 | % vic_out_dir
8 | % prefix
9 | % timestep_out = 'daily' or 'hourly'
10 | % headerlines
11 | %
12 | % Adapted from get_vic_run_metadata.m to allow different output filenames
13 | % besides 'eb' and 'wb'
14 |
15 | function info = get_vic_run_metadata2(vic_out_dir, timestep_out, prefix, varargin)
16 |
17 | if length(varargin) > 0
18 | headerlines = varargin{1};
19 | else
20 | headerlines = 3;
21 | end
22 |
23 | % Get metadata (lat, lon, time, names)
24 | fluxnames = dir(fullfile(vic_out_dir, [prefix, '*']));
25 |
26 | [lon, lat] = get_coordinates_from_VIC_file(vic_out_dir, prefix);
27 |
28 | sample_flux_file = fullfile(vic_out_dir, fluxnames(1).name);
29 |
30 | if headerlines == 3
31 | flux_varnames = get_vic_header(sample_flux_file, headerlines);
32 | info.vars = flux_varnames;
33 | end
34 |
35 | flux_out = dlmread(sample_flux_file, '\t', headerlines, 0);
36 | if size(flux_out) == 1
37 | flux_out = dlmread(sample_flux_file, ' ', headerlines, 0);
38 | end
39 |
40 | switch timestep_out
41 | case 'hourly'
42 | date_array = flux_out(:,1:4);
43 | timevector = datetime(date_array(:,1), date_array(:,2), date_array(:,3), 0, 0, date_array(:,4));
44 | case 'daily'
45 | date_array = flux_out(:,1:3);
46 | timevector = datetime(date_array(:,1), date_array(:,2), date_array(:,3));
47 | end
48 |
49 | info.time = timevector;
50 | info.ncells = length(fluxnames);
51 | info.nt = length(timevector);
52 | info.flux_out_dir = vic_out_dir;
53 | info.headerlines = headerlines;
54 |
55 | info.lon = lon;
56 | info.lat = lat;
57 | % info.lon = flipud(lon);
58 | % info.lat = flipud(lat); % should be in decreasing order
59 | % check_latlon(info.lat, info.lon);
60 |
61 | return
62 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/load_classic_mode_outputs.m:
--------------------------------------------------------------------------------
1 | % Load Classic Mode Inputs
2 | %
3 | % 8/5/2020 JRS
4 | % Loads classic mode outputs from VIC-5 Classic
5 | %
6 | % INPUTS
7 | % vic_out_dir = directory where raw VIC outputs are stored
8 | % prefix = prefix of VIC output files (e.g. 'fluxes'). Must include '_'
9 | % timestep_out = either 'daily' or
10 | % processed_dir = directory to store processed VIC outputs
11 | % basinmask = name of basin mask (geotiff)
12 | %
13 | % OUTPUT
14 | %
15 | % classic = structure containing all data from VIC simulation
16 | % This variable will be very large for a big VIC simulation
17 | %
18 | % For simulations with large numbers of grid cells and/or time steps, avoid
19 | % using load_classic_mode_outputs. Instead, refer to ucrb_wrapper.m or
20 | % similar. Can use load_outputs as toggle here. See below.
21 |
22 | function classic = load_classic_mode_outputs(vic_out_dir, prefix, timestep_out, processed_dir, basinmask)
23 |
24 | mkdir(processed_dir); % only need to do this if it doesn't already exist.
25 |
26 | % Post spin-up, original parameter simulation
27 | classic.outdir = vic_out_dir;
28 |
29 | classic.metadata = get_vic_run_metadata2(classic.outdir, timestep_out, prefix);
30 | classic.processed_dir = processed_dir;
31 | [basin_mask, Rmask, masklon, masklat] = geotiffread2(basinmask);
32 |
33 | if ~strcmp(class(basin_mask), 'double')
34 | basin_mask = double(basin_mask);
35 | end
36 |
37 | % starting index at 4 because the first three are year, month, and day
38 | for i=4:length(classic.metadata.vars)
39 | varname = classic.metadata.vars{i};
40 | savename = fullfile(classic.processed_dir, [varname '.mat']);
41 | try
42 | [classic.timevector, ~, classic.info] = load_vic_output2(classic.outdir, varname, prefix, 'daily', 1, savename);
43 | masksavename = fullfile(classic.processed_dir, [varname '_masked.mat']);
44 | mask_results_to_bb(savename, basin_mask, masksavename);
45 | catch
46 | disp(['Failed to process ' varname])
47 | disp(savename)
48 | disp(masksavename)
49 | end
50 | end
51 |
52 | load_outputs = 1; % toggle for loading processed outputs into MATLAB
53 |
54 | % Load classic outputs
55 | if load_outputs
56 | for i=4:length(classic.metadata.vars)
57 | varname = classic.metadata.vars{i};
58 | tempname = strsplit(varname, 'OUT_');
59 | masksavename = fullfile(classic.processed_dir, [varname '_masked.mat']);
60 | temp = load(masksavename);
61 | classic.out.(tempname{2}) = temp.output_map_masked;
62 | end
63 | end
64 |
65 | return
--------------------------------------------------------------------------------
/vicmatlab/outputs/load_vic_output.m:
--------------------------------------------------------------------------------
1 | % Function for loading one particular VIC variable, as a time series
2 | %
3 | % Can only read data from the wb output file, as written.
4 | %
5 | % Inspired by subset_livneh.m function for image mode variables, but this
6 | % version is for classic mode outputs. Code also draws heavily from
7 | % VICMATLAB::check_outputs_wrapper.m
8 | %
9 | % Inputs
10 | %
11 | %
12 | %
13 | % varargin = timestep_out, saveflag, savename
14 |
15 | function [timevector, var1, info] = load_vic_output(vic_out_dir, varname, varargin)
16 | % function [timevector, var_sub, var1, info] = load_vic_output(vic_out_dir, basin_mask, var_col)
17 |
18 | %% Parse optional arguments;
19 |
20 | numvarargs = length(varargin);
21 | if numvarargs > 3
22 | error('The max number of optional arguments is 3')
23 | end
24 |
25 | optargs = {'daily', 0, './varname.mat'};
26 | optargs(1:numvarargs) = varargin;
27 | [timestep_out, saveflag, savename] = optargs{:};
28 |
29 | info = get_vic_run_metadata(vic_out_dir, timestep_out);
30 |
31 | % [mask1, ~, lon1, lat1] = geotiffread2(basin_mask);
32 | % figure, plotraster(lon1, lat1, mask1, '','','')
33 |
34 | %% Parse the input variable name:
35 |
36 | fID = fopen('vic_output_lookup_table');
37 | lutable = textscan(fID, '%s%s%s');
38 | fclose(fID);
39 |
40 | % Search the table for a match
41 | var_index = find(strcmp(varname, lutable{1}));
42 | if isempty(var_index)
43 | var_index = find(strcmp(varname, lutable{2}));
44 | end
45 | if isempty(var_index)
46 | error('Variable not found. Check spelling.')
47 | end
48 |
49 | ebwb = lutable{3}{var_index};
50 | official_variable_name = lutable{2}{var_index};
51 | if strcmp(ebwb, 'wb')
52 | out_dir = fullfile(vic_out_dir, 'wb');
53 | var_col = find(strcmp(official_variable_name, info.wbvars));
54 | else
55 | out_dir = fullfile(vic_out_dir, 'eb');
56 | var_col = find(strcmp(official_variable_name, info.ebvars));
57 | end
58 |
59 | %% Load VIC output variable
60 |
61 | % Initialize arrays
62 | varnames = dir([out_dir '/*.txt']);
63 | dat = dlmread(fullfile(out_dir, varnames(1).name), '\t', 3, 0);
64 |
65 | % size(dat) % ndays by 27 for VICGlobal case
66 |
67 | timevector = datetime(dat(:,1), dat(:,2), dat(:,3));
68 |
69 | ndays = size(dat, 1);
70 | ncells = length(varnames);
71 | problem_flag = 0;
72 |
73 | var1 = zeros(ncells, ndays);
74 | for k=1:ncells
75 | dat = dlmread(fullfile(out_dir, varnames(k).name), '\t', 3, 0);
76 | try
77 | var1(k,:) = dat(:,var_col);
78 | catch
79 | % Some of the grid cells may not have run to completion for
80 | % whatever reason. If this happens, check to see what the problem
81 | % is with the VIC output files.
82 | if problem_flag == 0
83 | problem_flag = 1;
84 | disp('Some of the grid cells may not have run to completion')
85 | end
86 | nn = size(dat(:,var_col));
87 | var1(k,1:nn) = dat(:,var_col);
88 | end
89 | % 1 by ndays and ndays by 1 for VICGlobal case
90 | if mod(k,1000)==0
91 | disp(k) % update this to a proper progress bar
92 | end
93 | end
94 |
95 | %% Subset the variable (not implemented)
96 |
97 | % % There may or may not be a need to subset var1.
98 | % %
99 | % % It depends if the VIC simulation was run over the study basin, precisely,
100 | % % or if the simulation was run over a larger area and we wish to subset the
101 | % % results to the basin.
102 | % %
103 | % % The following code checks which case is happening and performs the
104 | % % appropriate computations:
105 | % %
106 | % % basinmask;
107 | % %
108 | % % mask_vect = mask1(:);
109 | % % var_sub = var1;
110 | % %
111 | % % if size(var_sub, 1) < length(mask_vect)
112 | % % disp('The number of VIC grid cells is smaller than or equal to the number of grid cells in the basin mask')
113 | % % else
114 | % % disp('The number of VIC grid cells is larger than the number of grid cells in the basin mask')
115 | % % disp('The user should crop the output to the basin mask.')
116 | % % disp('Attempting to crop the results to the basin mask')
117 | % % var_sub = var_sub(mask_vect==1,:);
118 | % % var_sub(mask_vect ~= 1,:) = [];
119 | % % end
120 | % %
121 | % % Use the mask to subset var1. See subset_netcdf_w_geotiff_mask.m from
122 | % % subset_livneh.m. Ideally, there is no need to call xyz2grid, and we can
123 | % % preserve the time-resolution of the data.
124 | % %
125 | % % [var_sub, ~, ~] = subset_netcdf_w_geotiffmask(var1, lon1, lat1, basin_mask);
126 | % % The above would work if var_sub were nx by ny by nt grid
127 | % %
128 | % % Will need to find another way (1/29/2020)
129 | % %
130 | % % ncells_in_mask = sum(sum(mask1>0));
131 | % % var_sub = NaN(ndays, ncells_in_mask);
132 |
133 | %% Save output (optional)
134 |
135 | if saveflag
136 | save(savename, 'timevector', 'var1', 'info');
137 | disp(['Saved variable to ' savename])
138 | end
139 |
140 | return
141 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/load_vic_output2.m:
--------------------------------------------------------------------------------
1 | % Function for loading one particular VIC variable, as a time series
2 | %
3 | % Inspired by subset_livneh.m function for image mode variables, but this
4 | % version is for classic mode outputs. Code also draws heavily from
5 | % VICMATLAB::check_outputs_wrapper.m
6 | %
7 | % Revised 8/4/2020 to be more flexible w/regard to inputs
8 | %
9 | % Inputs
10 | % varargin = timestep_out, saveflag, savename
11 |
12 | function [timevector, var1, info] = load_vic_output2(vic_out_dir, varname, prefix, varargin)
13 |
14 | %% Parse optional arguments;
15 |
16 | numvarargs = length(varargin);
17 | if numvarargs > 4
18 | error('The max number of optional arguments is 4')
19 | end
20 |
21 | optargs = {3, 'daily', 0, './varname.mat'};
22 | optargs(1:numvarargs) = varargin;
23 | [headerlines, timestep_out, saveflag, savename] = optargs{:};
24 |
25 | if strcmp(timestep_out, 'hourly')
26 | disp('timevector output will not have hours... This is a missing feature in the code.')
27 | end
28 |
29 | info = get_vic_run_metadata2(vic_out_dir, timestep_out, prefix, headerlines);
30 |
31 | %% Parse the input variable name:
32 |
33 | fID = fopen('vic_output_lookup_table');
34 | lutable = textscan(fID, '%s%s%s');
35 | fclose(fID);
36 |
37 | % Search the table for a match
38 | var_index = find(strcmp(varname, lutable{1}));
39 | if isempty(var_index)
40 | var_index = find(strcmp(varname, lutable{2}));
41 | end
42 | if isempty(var_index)
43 | error('Variable not found. Check spelling.')
44 | end
45 |
46 | official_variable_name = lutable{2}{var_index};
47 | var_col = find(strcmp(official_variable_name, info.vars));
48 |
49 | %% Load VIC output variable
50 |
51 | % Initialize arrays
52 | varnames = dir([vic_out_dir '/' prefix '*.txt']);
53 | % dat = dlmread(fullfile(vic_out_dir, varnames(1).name), '\t', 3, 0);
54 | dat = readmatrix(fullfile(vic_out_dir, varnames(1).name), 'headerlines', 3);
55 |
56 | timevector = datetime(dat(:,1), dat(:,2), dat(:,3));
57 |
58 | ndays = size(dat, 1);
59 | ncells = length(varnames);
60 | problem_flag = 0;
61 |
62 | var1 = zeros(ncells, ndays);
63 | for k=1:ncells
64 | % dat = dlmread(fullfile(vic_out_dir, varnames(k).name), '\t', 3, 0);
65 | dat = readmatrix(fullfile(vic_out_dir, varnames(k).name), 'headerlines', 3);
66 | try
67 | var1(k,:) = dat(:,var_col);
68 | catch
69 | % Some of the grid cells may not have run to completion for
70 | % whatever reason. If this happens, check to see what the problem
71 | % is with the VIC output files.
72 | if problem_flag == 0
73 | problem_flag = 1;
74 | disp('Some of the grid cells may not have run to completion')
75 | end
76 | nn = size(dat(:,var_col));
77 | var1(k,1:nn) = dat(:,var_col);
78 | end
79 | % 1 by ndays and ndays by 1 for VICGlobal case
80 | if mod(k,1000)==0
81 | disp(k) % update this to a proper progress bar
82 | end
83 | end
84 |
85 | %% Save output (optional)
86 |
87 | if saveflag
88 | save(savename, 'timevector', 'var1', 'info');
89 | disp(['Saved variable to ' savename])
90 | end
91 |
92 | return
93 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/load_vic_output_image.m:
--------------------------------------------------------------------------------
1 | % Loads outputs from VIC image mode into MATLAB
2 | %
3 | % Written 8/4/2020 JRS
4 |
5 | function FLUXES = load_vic_output_image(vic_out_name)
6 |
7 | % Load NetCDF file contents into Matlab
8 | info = ncinfo(vic_out_name);
9 | numvars = length(info.Variables);
10 | varnames = cell(numvars,1);
11 |
12 | for p=1:numvars
13 | varnames{p} = info.Variables(p).Name;
14 | var = ncread(vic_out_name, varnames{p});
15 |
16 | if ndims(var) == 4
17 | disp([varnames{p} 'has four dims'])
18 | FLUXES.(varnames{p}) = permute(var, [2,1,3,4]);
19 | else
20 | FLUXES.(varnames{p}) = permute(var, [2,1,3]);
21 | end
22 | end
23 |
24 | % Convert to datetime:
25 | FLUXES.time = datestr(FLUXES.time+367);
26 | FLUXES.time = datetime(FLUXES.time);
27 |
28 | return
--------------------------------------------------------------------------------
/vicmatlab/outputs/make_results_struct_wb.m:
--------------------------------------------------------------------------------
1 | function resultsstruct = make_results_struct_wb(results)
2 |
3 | resultsstruct = struct();
4 | resultsstruct.evap = results(:,4);
5 | resultsstruct.runoff = results(:,5);
6 | resultsstruct.baseflow = results(:,6);
7 | resultsstruct.canop_evap = results(:,7);
8 | resultsstruct.transp = results(:,8);
9 | resultsstruct.bare_soil_evap = results(:,9);
10 | resultsstruct.sub_canop = results(:,10);
11 | resultsstruct.sub_snow = results(:,11);
12 | resultsstruct.precip = results(:,13);
13 | resultsstruct.sm0 = results(:,21);
14 | resultsstruct.sm1 = results(:,22);
15 | resultsstruct.sm2 = results(:,23);
16 | resultsstruct.swe = results(:,27);
17 |
18 | return
--------------------------------------------------------------------------------
/vicmatlab/outputs/mask_results_to_bb.m:
--------------------------------------------------------------------------------
1 | % Mask results to basin boundary
2 | %
3 | % INPUTS
4 | % Basin mask
5 | % Name of .mat file where load_vic_output saved the processed VIC outputs
6 | % Optional: filename to save the cropped VIC output
7 | %
8 | %
9 | % If the VIC results are for more grid cells than the basin covers, use
10 | % this function to mask the VIC results to the basin boundary
11 |
12 | function [output_map_masked, R] = mask_results_to_bb(savename, basinmask, varargin)
13 |
14 | if strcmp(class(basinmask), 'double')
15 | basinmask = double(basinmask);
16 | end
17 |
18 | disp('masking')
19 |
20 | % Do the masking
21 | output = load(savename);
22 | nt = length(output.timevector);
23 | [nlon, nlat] = size(basinmask);
24 | output_map_masked = NaN(nlon, nlat, nt);
25 | disp(['There are ' num2str(nt) ' time steps'])
26 | for t=1:nt
27 | output_map = xyz2grid(output.info.lon, output.info.lat, output.var1(:,t));
28 |
29 | if t==1
30 | if size(output_map,1) ~= size(basinmask,1) || size(output_map,2) ~= size(basinmask,2)
31 | % Sometimes the basinmask has an extra row and column compared to
32 | % the 'output_map'. Remove it if necessary. This issue could
33 | % probably be avoided by being more careful about coordinate
34 | % systems
35 | disp('Removing extra rows and/or columns from basinmask')
36 | basinmask = remove_empty_rowcol(basinmask);
37 | [nlon, nlat] = size(basinmask);
38 | output_map_masked = NaN(nlon, nlat, nt);
39 | end
40 | end
41 |
42 | output_map_masked(:,:,t) = output_map.*basinmask;
43 | if mod(t,1000)==0
44 | disp(t)
45 | end
46 | end
47 |
48 | % Make georeferencing matrix
49 | resolution = max(abs(diff(output.info.lat)));
50 | R = makerefmat(min(output.info.lon), min(output.info.lat), resolution, resolution);
51 |
52 | % geotiffwrite('./evap.tif', output_map_masked(:,:,1), R);
53 |
54 | % Save the output (optional)
55 | if ~isempty(varargin)
56 | save(varargin{1}, 'output_map_masked', 'R')
57 | disp('saved mask for current variable')
58 | end
59 |
60 |
61 |
62 | return
63 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/myKGE.m:
--------------------------------------------------------------------------------
1 | % Calculates KGE
2 |
3 | function KGE = myKGE(y, y_hat)
4 |
5 | % remove NaNs
6 | A = [y, y_hat];
7 | i1 = isnan(A);
8 | i2 = find(sum(i1, 2) > 0);
9 | A(i2,:) = [];
10 | y = A(:,1);
11 | y_hat = A(:,2);
12 |
13 | r = corr(y,y_hat); % correlation
14 | alpha1 = std(y_hat)/std(y); % relative variability
15 | beta1 = mean(y_hat)/mean(y); % bias
16 | KGE = 1 - sqrt((r - 1)^2 + (alpha1 - 1)^2 + (beta1 - 1)^2);
17 |
18 | return
19 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/myNSE.m:
--------------------------------------------------------------------------------
1 | % Calculates NSE
2 |
3 | function NSE = myNSE(y, y_hat)
4 |
5 | % remove NaNs
6 | A = [y, y_hat];
7 | i1 = isnan(A);
8 | i2 = find(sum(i1, 2) > 0);
9 | A(i2,:) = [];
10 | y = A(:,1);
11 | y_hat = A(:,2);
12 |
13 | SSE = (y_hat - y)'*(y_hat - y);
14 | y_mean = mean(y);
15 | sum2 = (y - y_mean)'*(y- y_mean);
16 | NSE = 1 - SSE/sum2;
17 |
18 | return
19 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/myRMSE.m:
--------------------------------------------------------------------------------
1 | % Calculates RMSE
2 |
3 | function RMSE = myRMSE(y, y_hat)
4 |
5 | % remove NaNs
6 | A = [y, y_hat];
7 | i1 = isnan(A);
8 | i2 = find(sum(i1, 2) > 0);
9 | A(i2,:) = [];
10 | y = A(:,1);
11 | y_hat = A(:,2);
12 |
13 | SSE = (y_hat - y)'*(y_hat - y);
14 | N = length(y);
15 | RMSE = sqrt(SSE/N);
16 |
17 | return
18 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/parload.m:
--------------------------------------------------------------------------------
1 | % ParLoad
2 | %
3 | % Loads VIC outputs using a parallel pool
4 | % Enter n = 0 if you don't want to use a parallel pool
5 |
6 | function out1 = parload(outdir, prefix, varargin)
7 |
8 | headerrows = 0;
9 |
10 | numvarargs = length(varargin);
11 | if numvarargs > 2
12 | error('The max number of optional arguments is 2')
13 | end
14 |
15 | optargs = {2, []};
16 | optargs(1:numvarargs) = varargin;
17 | [n, col] = optargs{:};
18 |
19 | disp(['Using n = ' num2str(n)])
20 |
21 | if n>6
22 | disp(['n = ' num2str(n)])
23 | disp('Consider using fewer processors')
24 | elseif n==0
25 | disp(['n = ' num2str(n)])
26 | disp('Not using a parallel pool')
27 | end
28 |
29 | wbnames = dir(fullfile(outdir, [prefix '*']));
30 | ncells = length(wbnames);
31 | out0 = dlmread(fullfile(outdir, wbnames(1).name), '\t', headerrows, 0);
32 | if size(out0,2) == 1
33 | out0 = dlmread(fullfile(outdir, wbnames(1).name), ' ', headerrows, 0);
34 | end
35 | [nt, nvar] = size(out0);
36 |
37 | if isempty(col)
38 | % Read all columns
39 | C1 = 0;
40 | C2 = nvar-1;
41 | out1 = zeros(nt, ncells, nvar);
42 | else
43 | % Read a single column
44 | C1 = col-1;
45 | C2 = col-1;
46 | out1 = zeros(nt, ncells);
47 | end
48 |
49 | if n>0
50 |
51 | % Check if parallel pool exists
52 | if isempty(gcp('nocreate'))
53 | parpool(n);
54 | end
55 | % delete(gcp('nocreate'))
56 |
57 | parfor k=1:ncells
58 | out1(:,k,:) = dlmread(fullfile(outdir, wbnames(k).name), '\t', [headerrows, C1, nt+(headerrows - 1), C2]);
59 | end
60 |
61 | else
62 |
63 | try
64 | for k=1:ncells
65 | out1(:,k,:) = dlmread(fullfile(outdir, wbnames(k).name), '\t', [headerrows, C1, nt+(headerrows - 1), C2]);
66 | end
67 | catch
68 | for k=1:ncells
69 | out1(:,k,:) = dlmread(fullfile(outdir, wbnames(k).name), ' ', [headerrows, C1, nt+(headerrows - 1), C2]);
70 | end
71 | end
72 |
73 | end
74 | end
--------------------------------------------------------------------------------
/vicmatlab/outputs/subset_outputs_to_spf.m:
--------------------------------------------------------------------------------
1 | % Subset forcings
2 | %
3 | % Copy over ASCII outputs for a particular basin
4 | %
5 | % Example:
6 | % subset_outputs_to_spf(soilfile, forcdir, 'Forcings_')
7 | % soilfile = '/Volumes/HD3/SWOTDA/Calibration/Bhakra/soils_bhakra.txt';
8 | % prefix = 'wb_';
9 | % forcdir = '/Volumes/HD4/SWOTDA/Data/IRB/Downscaled_Forcings/ascii_1980-2019';
10 | % newforcdir = '/Volumes/HD4/SWOTDA/Data/IRB/ascii_1980-2019';
11 |
12 | function [soil_lon, soil_lat] = subset_outputs_to_spf(soilfile, forcdir, prefix, newforcdir)
13 |
14 | mkdir(newforcdir)
15 |
16 | soils = load(soilfile);
17 | forcnames = dir([fullfile(forcdir, prefix) '*']);
18 |
19 | [lon, lat] = get_coordinates_from_VIC_file(forcdir, prefix);
20 |
21 | soil_lat = soils(:,3);
22 | soil_lon = soils(:,4);
23 |
24 | ncells = length(soil_lat);
25 | T = delaunayn([lat, lon]);
26 | disp(['There are ' num2str(ncells) ' grid cells'])
27 | for j=1:ncells
28 | k = dsearchn([lat, lon],T,[soil_lat(j) soil_lon(j)]);
29 | origfile = fullfile(forcdir, forcnames(k).name);
30 | newfile = fullfile(newforcdir, forcnames(k).name);
31 | copyfile(origfile, newfile);
32 | if mod(j,100)==0
33 | disp(num2str(j))
34 | end
35 | end
36 |
37 | return
38 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/vic_output_lookup_table:
--------------------------------------------------------------------------------
1 | year YEAR eb
2 | month MONTH eb
3 | day DAY eb
4 | net_radiation OUT_R_NET eb
5 | net_sw OUT_SWNET eb
6 | net_lw OUT_LWNET eb
7 | incoming_lw OUT_IN_LONG eb
8 | sensible OUT_SENSIBLE eb
9 | latent OUT_LATENT eb
10 | ground_flux OUT_GRND_FLUX eb
11 | energy_error OUT_ENERGY_ERROR eb
12 | albedo OUT_ALBEDO eb
13 | aerodynamic_resistance OUT_AERO_RESIST eb
14 | wind OUT_WIND eb
15 | air_temperature OUT_AIR_TEMP eb
16 | surface_temperature OUT_SURF_TEMP eb
17 | evaporation OUT_EVAP wb
18 | runoff OUT_RUNOFF wb
19 | baseflow OUT_BASEFLOW wb
20 | evap_canopy OUT_EVAP_CANOP wb
21 | transpiration OUT_TRANSP_VEG wb
22 | evap_bare OUT_EVAP_BARE wb
23 | sub_canopy OUT_SUB_CANOP wb
24 | sub_snow OUT_SUB_SNOW wb
25 | pet OUT_PET wb
26 | precipitation OUT_PREC wb
27 | rainf OUT_RAINF wb
28 | snowf OUT_SNOWF wb
29 | water_error OUT_WATER_ERROR wb
30 | wdew OUT_WDEW wb
31 | soil_liq0 OUT_SOIL_LIQ_0 wb
32 | soil_liq1 OUT_SOIL_LIQ_1 wb
33 | soil_liq2 OUT_SOIL_LIQ_2 wb
34 | sm0 OUT_SOIL_MOIST_0 wb
35 | sm1 OUT_SOIL_MOIST_1 wb
36 | sm2 OUT_SOIL_MOIST_2 wb
37 | snow_cover OUT_SNOW_COVER wb
38 | snow_depth OUT_SNOW_DEPTH wb
39 | snow_canop OUT_SNOW_CANOPY wb
40 | swe OUT_SWE wb
41 |
42 |
--------------------------------------------------------------------------------
/vicmatlab/outputs/vic_outputs_names_table.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/vicmatlab/outputs/vic_outputs_names_table.ods
--------------------------------------------------------------------------------
/vicmatlab/parallel/read_global_param_file.m:
--------------------------------------------------------------------------------
1 | % Writes out the VIC global parameter file
2 |
3 | function A = read_global_param_file(fname)
4 |
5 | fid = fopen(fname, 'r');
6 | i = 1;
7 | tline = fgetl(fid);
8 | A{i} = tline;
9 | while ischar(tline)
10 | i = i+1;
11 | tline = fgetl(fid);
12 | A{i} = tline;
13 | end
14 | fclose(fid);
15 |
16 | return
--------------------------------------------------------------------------------
/vicmatlab/parallel/set_up_parallel.m:
--------------------------------------------------------------------------------
1 | % Set up parallel
2 | %
3 | % Subsets the VIC soil parameter file into multiple, smaller soil parameter files
4 | % and generates corresponding copies of the VIC global parameter file for running
5 | % VIC 4 or VIC 5 Classic in parallel as a job array on Hoffman2.
6 | % This works because computations for one grid cell are independent of other grid cells.
7 | %
8 | % Written by Dongyue Li 4/2019
9 | % Modified 5/1/2019 JRS
10 | % Updated 11/18/2019 JRS to be a function, not a script
11 | % Updated 7/18/2020 JRS to use a simpler directory structure
12 | %
13 | % INPUTS
14 | % outdir = Directory where VIC should save outputs (the parallel inputs will be
15 | % written here, too)
16 | % soil_param = Name of soil parameter file
17 | % global_param_file = Name of global parameter file
18 | % n_proc = Number of processors to use
19 | % vic_command = command to call VIC
20 |
21 | function outname = set_up_parallel(control_params)
22 |
23 | %% Inputs
24 |
25 | mkdir(control_params.vic_outdir);
26 | mkdir(control_params.log_outdir);
27 | mkdir(control_params.vic_indir);
28 |
29 | [~, soil_basename, ~] = fileparts(control_params.soil_param);
30 | [~, global_basename, ~] = fileparts(control_params.global_param_file);
31 |
32 | soils_all = dlmread(control_params.soil_param);
33 | ncells = size(soils_all, 1);
34 |
35 | % how many divisions to divide the soil parameter file into
36 | n = control_params.n_proc;
37 | nl = ceil(ncells/n);
38 |
39 | %% Make copies of the global parameter file
40 |
41 | % Lines in the global parameter file where the soil parameters, results,
42 | % and log inputs are specified. Detect automatically.
43 |
44 | soil_line = find_line(control_params.global_param_file, 'Soil parameter path/file');
45 | result_line = find_line(control_params.global_param_file, 'RESULT_DIR');
46 | log_line = find_line(control_params.global_param_file, 'LOG_DIR');
47 |
48 | for jj=1:n
49 |
50 | A = read_global_param_file(control_params.global_param_file);
51 |
52 | % change the soil parameter line
53 | A{soil_line} = ['SOIL ' fullfile(control_params.vic_indir, [soil_basename, '_', num2str(jj), '.txt'])];
54 |
55 | % change the output directory
56 | A{log_line} = ['LOG_DIR ' control_params.log_outdir];
57 | A{result_line} = ['RESULT_DIR ' control_params.vic_outdir];
58 |
59 | % Write out the modified global parameter file
60 | sn = fullfile(control_params.vic_indir, [global_basename, '_', num2str(jj), '.txt']);
61 | write_global_param_file(A, sn)
62 |
63 | end
64 |
65 | %% Subdivide the soil parameter file
66 |
67 | for jj=1:n
68 |
69 | if jj==n
70 | soils_sub = soils_all((jj-1)*nl+1:ncells,:);
71 | else
72 | soils_sub = soils_all((jj-1)*nl+1:(jj-1)*nl+nl,:);
73 | end
74 |
75 | outname = fullfile(control_params.vic_indir, [soil_basename, '_', num2str(jj) '.txt']);
76 | precision = 5;
77 | write_soils(precision, soils_sub, outname, control_params.soil_format);
78 |
79 | end
80 |
81 | %% Make the VIC parallel wrapper
82 |
83 | [globpath, globname globext] = fileparts(control_params.global_param_file);
84 | % parfilenam = fullfile(globpath, [globname '_${SGE_TASK_ID}' globext]);
85 | parfilenam = fullfile(control_params.vic_indir, [globname '_${SGE_TASK_ID}' globext]);
86 | vic_run_command = [control_params.vic_command ' -g ' parfilenam];
87 |
88 | outname = fullfile(fileparts(control_params.vic_indir), 'vic_parallel_wrapper.sh');
89 | A = cell(3,1);
90 |
91 | % Different command file for local computer vs. Hoffman2
92 | if control_params.local
93 | A{1} = '#!/bin/bash';
94 | A{2} = ['for SGE_TASK_ID in {1..', num2str(control_params.n_proc), '}'];
95 | A{3} = 'do';
96 | A{4} = 'echo $SGE_TASK_ID';
97 | A{5} = [vic_run_command, ' &']; % run in background
98 | A{6} = 'done';
99 | A{7} = -1;
100 | else
101 | A{1} = '#!/bin/bash';
102 | A{2} = 'echo $SGE_TASK_ID';
103 | A{3} = vic_run_command;
104 | A{4} = -1;
105 | end
106 |
107 | write_global_param_file(A, outname)
108 | system(['chmod +x ' outname])
109 | disp(['Wrote exec file to ' outname])
110 |
111 | return
112 |
113 | %% Scrap
114 |
115 | % global_param_file = '/Volumes/HD4/SWOTDA/Data/IRB/VIC/FullDomain/globalparam_WB_SB_1980-2018.txt';
116 | % soil_parameter_file = '/Volumes/HD4/SWOTDA/Data/IRB/VIC/FullDomain/soils_snapped.SB';
117 | % savedir_soil = savedir; % directory to save the subsetted soil param files
118 | % savedir = '/Volumes/HD4/SWOTDA/Data/IRB/VIC/FullDomain/vic_parallel_WB_1980-2018'; % directory to save the newly created global param files
119 | % global_basename = './global_param_irb';
120 | % ncells = 75231;
121 | % nl = 1000; % number of grid cells to keep in each soil parameter file
122 | % n = ceil(ncells/nl);
123 | % Create n directories so the outputs from each division are saved in different directories (for debugging purposes)
124 | % outdir_names = cell(n,1);
125 | % for jj=1:n
126 | % outdir_names{jj} = fullfile(savedir_out, ['Output_' num2str(jj)]);
127 | % % mkdir(outdir_names{jj})
128 | % end
--------------------------------------------------------------------------------
/vicmatlab/parallel/set_up_parallel_wrapper.m:
--------------------------------------------------------------------------------
1 | % Parallel wrapper
2 | %
3 | % Written 11/25/2019 JRS
4 | %
5 | % Sets up the VIC global parameter and soil parameter files for a
6 | % multi-processor run on Hoffman2.
7 | %
8 | % Eventually, it would be cool to make a script that completely prepares
9 | % the global parameter file from scratch based on a Matlab wrapper,
10 | % potentially with a GUI, like Sungwook Wi did in VIC-ASSIST.
11 |
12 | addpath(genpath('/home/jschap/Documents/Codes/VICMATLAB/vicmatlab'))
13 |
14 | % /u/home/j/jschaper/vic/VICGlobal/v1_5/Classic/veglib_nh_new_resist.txt
15 |
16 | %%
17 |
18 | % cd '/Volumes/HD3/SWOTDA'
19 | cd ~/Documents/ESSD
20 |
21 | % template soil parameter filename
22 | % control_params.soil_param = '/Volumes/HD4/SWOTDA/Data/Colorado/colo_soils_L13.txt';
23 | % control_params.soil_param = '/Volumes/HD4/SWOTDA/Data/UpperMiss/umrb_soils_vg.txt';
24 | control_params.soil_param = '/home/jschap/Documents/ESSD/clipped_soils_VG.txt';
25 |
26 | % template global parameter filename
27 | control_params.global_param = '/home/jschap/Documents/hoffman2transfer/global_param_WY2001-2011.txt';
28 | % control_params.global_param = '/Volumes/HD4/SWOTDA/Data/UpperMiss/remote_par_classic_vg_1980-2011.txt';
29 |
30 | % location where parallelized inputs for the VIC model should be saved
31 | control_params.out_dir = '/home/jschap/Documents/hoffman2transfer/parallel/';
32 | % control_params.out_dir = '/Volumes/HD4/SWOTDA/Data/UpperMiss/parallel';
33 |
34 | % full path for the VIC executable
35 | control_params.vic_command = '/u/home/j/jschaper/vic/VIC-VIC.5.1.0.rc1/vic/drivers/classic/vic_classic.exe';
36 |
37 | % location on Hoffman2 to write VIC outputs
38 | control_params.vic_out_dir = '/u/scratch/j/jschaper/UCRB/WB_WY2001-2011_VG/';
39 |
40 | % location on Hoffman2 from which global parameter files and soil parameter files will be read
41 | % control_params.vic_in_dir = '/u/home/j/jschaper/vic/UMRB/EB_1980-2011/parallel';
42 | control_params.vic_in_dir = '/u/scratch/j/jschaper/UCRB/WB_WY2001-2011_VG/parallel';
43 |
44 | control_params.n_proc = 100; % number of processors
45 | control_params.multidir = 0; % flag for using one or multiple directories for VIC outputs
46 | control_params.soil_format = '3l'; % 3l or livneh
47 |
48 | % cd '/Users/jschap/Documents/Codes/VICMATLAB/Control'
49 | set_up_parallel(control_params)
50 | % cd '/Volumes/HD3/SWOTDA'
51 |
52 | % Remember to create output directories on Hoffman2 before executing the
53 | % script.
54 |
55 | %% Sample inputs
56 |
57 | % control_params = struct();
58 | % % control_params.vic_out_dir = '/Volumes/HD4/SWOTDA/Data/IRB/EB_JF1980';
59 | % control_params.vic_out_dir = '/u/scratch/j/jschaper/EB_JF1980';
60 | % control_params.soil_param = '/Volumes/HD4/SWOTDA/Data/IRB/soils_irb.txt';
61 | % control_params.global_param_file = '/Volumes/HD4/SWOTDA/Data/IRB/par_EB_JF1980.txt';
62 | % control_params.n_proc = 40;
63 | % control_params.vic_command = '/u/home/j/jschaper/vic/VIC-VIC.5.1.0.rc1/vic/drivers/classic/vic_classic.exe';
64 |
65 | % control_params = struct();
66 | % control_params.vic_out_dir = '/u/scratch/j/jschaper/EB_JF1980';
67 | % control_params.soil_param = '/u/home/j/jschaper/vic/IRB/irb_soils.txt';
68 | % control_params.global_param_file = '/u/home/j/jschaper/vic/IRB/par_EB_JF1980.txt';
69 | % control_params.n_proc = 40;
70 | % control_params.vic_command = '';
--------------------------------------------------------------------------------
/vicmatlab/parallel/write_global_param_file.m:
--------------------------------------------------------------------------------
1 | % Writes out the VIC global parameter file
2 |
3 | function write_global_param_file(A, outname)
4 |
5 | fid = fopen(outname, 'w');
6 | for i=1:numel(A)
7 | if A{i+1} == -1 % MATLAB may read the final line as '-1'
8 | fprintf(fid,'%s\n', A{i});
9 | break
10 | else
11 | fprintf(fid,'%s\n', A{i});
12 | end
13 | end
14 | fclose(fid);
15 |
16 | return
--------------------------------------------------------------------------------
/vicmatlab/routing/convert_routing_inputs.m:
--------------------------------------------------------------------------------
1 | % Creates input files for the Lohmann routing model
2 | %
3 | % Written 10/23/2019 JRS
4 | % Updated (made function) 8/12/2020 JRS
5 | % Could be improved re: reading in VIC output files; there is some relevant
6 | % code elsewhere in VICMATLAB
7 | %
8 | % Also useful:
9 | % Remove extension from VIC output files
10 | % for file in fluxes*.txt; do mv "$file" "${file%.txt}"; done
11 |
12 | function convert_routing_inputs(vic_out_dir, rout_in_dir)
13 |
14 | fnames = dir([vic_out_dir '/wb_*']);
15 |
16 | ncells = length(fnames);
17 |
18 | if ~exist(rout_in_dir, 'dir')
19 | mkdir(rout_in_dir)
20 | disp(['Created directory: ' rout_in_dir])
21 | end
22 |
23 | for k=1:ncells
24 |
25 | dat = dlmread(fullfile(vic_out_dir, fnames(k).name), '\t', 3, 0);
26 | nt = size(dat,1);
27 | % A = [dat(:,1:3), zeros(nt,1), zeros(nt,1), dat(:,6), dat(:,7)];
28 |
29 | A = [dat(:,1:3), zeros(nt,1), zeros(nt,1), dat(:,5), dat(:,6)];
30 | outname = ['fluxes_' fnames(k).name(4:end)]; % if name is wb_
31 | % outname = ['fluxes_' fnames(k).name(10:end)]; % if name is fluxes_ or wb_daily
32 | dlmwrite(fullfile(rout_in_dir, outname), A, '\t')
33 |
34 | end
35 |
36 | return
--------------------------------------------------------------------------------
/vicmatlab/routing/remove_headers.m:
--------------------------------------------------------------------------------
1 | %% Remove headers
2 |
3 | % VIC 5 Classic output files come with three lines of header rows. In order
4 | % to run the VIC routing model with VIC 5 outputs, these header rows need
5 | % to be removed.
6 | %
7 | % Also useful:
8 | % Remove extension from VIC output files
9 | % for file in fluxes*.txt; do mv "$file" "${file%.txt}"; done
10 |
11 | function outdir = remove_headers(indir, outdir, prefix)
12 |
13 | orignames = dir(fullfile(indir, [prefix '*']));
14 | ncells = length(orignames);
15 | header_rows = 3;
16 | for k=1:ncells
17 | data = dlmread(fullfile(indir, orignames(k).name), '\t', header_rows, 0);
18 | dlmwrite(fullfile(outdir, orignames(k).name), data, ' ');
19 | if mod(k, 1000)==0
20 | disp(['Processed ' num2str(k) ' of ' num2str(ncells) ' files'])
21 | end
22 | end
--------------------------------------------------------------------------------
/vicmatlab/soils/get_soil_var_names.m:
--------------------------------------------------------------------------------
1 | % Get soil variable names
2 | %
3 | % Outputs the names of the columns in the soil parameter file, depending on
4 | % the model setup you wish to use
5 | %
6 | % setup = 2L, 2L-no-org-fs-july_tavg, 3L, 3L-no-org-frost-msds, livneh
7 |
8 | function varnames = get_soil_var_names(setup)
9 |
10 | switch setup
11 |
12 | case '2L'
13 |
14 | % Two-layer soil parameter file
15 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % all
16 | 'ws','c','expt1','expt2','ksat1','ksat2','phi_s1','phi_s2', ...
17 | 'init_moist1','init_moist2','elev','depth1','depth2','avg_T', ...
18 | 'dp','bubble1','bubble2','quartz1','quartz2','bulk_dens1','bulk_dens2', ...
19 | 'soil_dens1','soil_dens2','organic1','organic2','bdo1','bdo2','sdo1','sdo2', ...
20 | 'off_gmt','wcr_fract1','wcr_fract2','wpwp_fract1','wpwp_fract2','rough','snow_rough', ...
21 | 'annual_prec','resid_moist1','resid_moist2','fs_active','frost_slope','msds','july_Tavg'};
22 |
23 | case '2L-no-org-fs-july_tavg'
24 |
25 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % no organic, no frozen soil, no July_Tavg
26 | 'ws','c','expt1','expt2','ksat1','ksat2','phi_s1','phi_s2', ...
27 | 'init_moist1','init_moist2','elev','depth1','depth2','avg_T', ...
28 | 'dp','bubble1','bubble2','quartz1','quartz2','bulk_dens1','bulk_dens2', ...
29 | 'soil_dens1','soil_dens2', ...
30 | 'off_gmt','wcr_fract1','wcr_fract2','wpwp_fract1','wpwp_fract2','rough','snow_rough', ...
31 | 'annual_prec','resid_moist1','resid_moist2'};
32 |
33 | case '3L'
34 |
35 | % Three-layer soil parameter file (assuming top two layers are identical
36 | % given limited data)
37 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % all
38 | 'ws','c','expt1','expt2','expt3','ksat1','ksat2','ksat3','phi_s1','phi_s2','phi_s3', ...
39 | 'init_moist1','init_moist2','init_moist3','elev','depth1','depth2','depth3','avg_T', ...
40 | 'dp','bubble1','bubble2','bubble3','quartz1','quartz2','quartz3','bulk_dens1','bulk_dens2','bulk_dens3', ...
41 | 'soil_dens1','soil_dens2','soil_dens3','organic1','organic2','organic3','bdo1','bdo2','bdo3','sdo1','sdo2','sdo3', ...
42 | 'off_gmt','wcr_fract1','wcr_fract2','wcr_fract3','wpwp_fract1','wpwp_fract2','wpwp_fract3','rough','snow_rough', ...
43 | 'annual_prec','resid_moist1','resid_moist2','resid_moist3','fs_active','frost_slope','msds','july_Tavg'};
44 |
45 | case '3L-no-org-frost-msds'
46 |
47 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % three layers, no organic, no frost slope or msds
48 | 'ws','c','expt1','expt2','expt3','ksat1','ksat2','ksat3','phi_s1','phi_s2','phi_s3', ...
49 | 'init_moist1','init_moist2','init_moist3','elev','depth1','depth2','depth3','avg_T', ...
50 | 'dp','bubble1','bubble2','bubble3','quartz1','quartz2','quartz3','bulk_dens1','bulk_dens2','bulk_dens3', ...
51 | 'soil_dens1','soil_dens2','soil_dens3', ...
52 | 'off_gmt','wcr_fract1','wcr_fract2','wcr_fract3','wpwp_fract1','wpwp_fract2','wpwp_fract3','rough','snow_rough', ...
53 | 'annual_prec','resid_moist1','resid_moist2','resid_moist3','fs_active','july_Tavg'};
54 |
55 | case 'livneh'
56 |
57 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % Livneh
58 | 'ws','c','expt1','expt2','expt3','ksat1','ksat2','ksat3','phi_s1','phi_s2','phi_s3', ...
59 | 'init_moist1','init_moist2','init_moist3','elev','depth1','depth2','depth3','avg_T', ...
60 | 'dp','bubble1','bubble2','bubble3','quartz1','quartz2','quartz3','bulk_dens1','bulk_dens2','bulk_dens3', ...
61 | 'soil_dens1','soil_dens2','soil_dens3', ...
62 | 'off_gmt','wcr_fract1','wcr_fract2','wcr_fract3','wpwp_fract1','wpwp_fract2','wpwp_fract3','rough','snow_rough', ...
63 | 'annual_prec','resid_moist1','resid_moist2','resid_moist3','fs_active'};
64 |
65 | otherwise
66 |
67 | disp('Please enter a valid option for setup')
68 |
69 | end
70 |
71 |
72 | return
--------------------------------------------------------------------------------
/vicmatlab/soils/make_soil_tifs.m:
--------------------------------------------------------------------------------
1 | % Make soil tifs
2 | %
3 | % Generates tif files from the soil parameter file
4 | % Taken from subset_soils()
5 | %
6 | % Usage
7 | % soils_subset = load('soil_parameter_file.txt');
8 | % setup = 'livneh';
9 | % soil_var_path = 'output_directory';
10 | % [basin, Rsub, ~, ~] = geotiffread2('basinmask.tif');
11 | % make_soil_tifs(soils_subset, setup, soil_var_path, Rsub);
12 |
13 | function make_soil_tifs(soils_subset, setup, soil_var_path, Rsub)
14 |
15 | if ~exist(soil_var_path, 'dir')
16 | mkdir(soil_var_path)
17 | end
18 |
19 | varnames = get_soil_var_names(setup);
20 | lat_vect = soils_subset(:,3);
21 | lon_vect = soils_subset(:,4);
22 |
23 | if length(varnames)~=size(soils_subset,2)
24 | error('Check that the value for setup is correct')
25 | end
26 |
27 | for k=1:length(varnames)
28 | svar = soils_subset(:,k);
29 | svar_map = xyz2grid(lon_vect, lat_vect, svar);
30 | soutname = fullfile(soil_var_path, [varnames{k} '.tif']);
31 | geotiffwrite(soutname, flipud(svar_map), Rsub);
32 | end
33 | disp(['Geotiff files saved to ', soil_var_path]);
34 |
35 | end
--------------------------------------------------------------------------------
/vicmatlab/soils/myregrid.m:
--------------------------------------------------------------------------------
1 | % My Regrid
2 | %
3 | % Regrids georeferenced, gridded data to a finer or coarser resolution
4 | % Used in make_soil_file.m
5 | %
6 | % INPUTS
7 | % original and target coordinates
8 | % original resolution gridded data
9 | % method = 'nearest' or 'linear' or 'cubic', etc.
10 | %
11 | % Example:
12 | % lat = ncread('../HWSD/HWSD_1247/data/T_SAND.nc4', 'lat');
13 | % lon = ncread('../HWSD/HWSD_1247/data/T_SAND.nc4', 'lon');
14 | % target_lon = min(lon):0.0625:max(lon);
15 | % target_lat = min(lat):0.0625:max(lat);
16 | % [lons, lats] = ndgrid(lon, lat);
17 | % [rglons, rglats] = ndgrid(target_lon, target_lat);
18 | % t_sand_rg = myregrid(lons, lats, rglons, rglats, t_sand)';
19 |
20 | function rg = myregrid(olons, olats, rglons, rglats, og, method)
21 |
22 | F = griddedInterpolant(olons', olats', og', method);
23 | rg = F(rglons, rglats);
24 |
25 | end
--------------------------------------------------------------------------------
/vicmatlab/soils/reassign_soil_parameters.m:
--------------------------------------------------------------------------------
1 | % Reassign soil parameters
2 | %
3 | % 8/16/2020 JRS
4 | % Reassigns soil parameters from one soil parameter file (e.g. L2013) to
5 | % another (e.g. VICGlobal).
6 | %
7 | % INPUTS
8 | % spf1 = name of first soil parameter file
9 | % spf2 = name of second soil parameter file
10 | % cols = columns of first soil parameter file to transfer to second
11 | %
12 | % Note: code requires columns of first and second spfs to match
13 |
14 | function soils_VG = reassign_soil_parameters(spf1, spf2, cols)
15 |
16 | soils_L13 = load(spf1);
17 | soils_VG = load(spf2);
18 |
19 | lat_vg = soils_VG(:,3);
20 | lon_vg = soils_VG(:,4);
21 |
22 | lat_L13 = soils_L13(:,3);
23 | lon_L13 = soils_L13(:,4);
24 |
25 | T = delaunayn([lat_vg, lon_vg]);
26 | ncells = length(lon_vg);
27 | disp(['There are ' num2str(ncells) ' grid cells'])
28 | nvars = length(cols);
29 | for j=1:ncells
30 | k = dsearchn([lat_L13, lon_L13],T,[lat_vg(j) lon_vg(j)]);
31 | % soils_VG(j,3:4) == soils_L13(k,3:4); % lon/lat
32 | for i = 1:nvars
33 | soils_VG(j,cols(i)) = soils_L13(k,cols(i));
34 | end
35 | end
36 |
37 | outformat = '3l';
38 | precision = 5;
39 | temp = strsplit(spf2, '.txt');
40 | outname = [temp{1} '_reassigned.txt'];
41 | write_soils(precision, soils_VG, outname, outformat)
42 |
43 | return
--------------------------------------------------------------------------------
/vicmatlab/soils/subset_soils.m:
--------------------------------------------------------------------------------
1 | % Clips soil parameter file to basin extent
2 | %
3 | % INPUTS
4 | % soils = soil parameter file encompassing a region at least as large as the basin
5 | % landmask = land mask used to generate the soil parameter file
6 | % extent = bounding box or shapefile for subsetting
7 | % outname = Name of output
8 | % outformat = format of output ('3l'). See write_soils.m
9 | % grid_decimal = precision used in forcing filenames
10 | % setup = describes format. Can be 2L, 2L-no-org-fs-july_tavg, 3L, 3L-no-org-frost-msds, livneh
11 | %
12 | % OUTPUTS
13 | % Clipped soil parameter file
14 | %
15 | % Modified 1/22/2020 JRS
16 | % Does a somewhat better job subsetting to a basin mask/matching the extent of the
17 | % basin mask
18 |
19 | function [soils_subset, soil_var_path] = subset_soils(soils, extent, ...
20 | outname, outformat, grid_decimal, generate_tif, setup)
21 |
22 | % 9/11/2020 JRS modifies this for 1/4 degree UMRB setup
23 |
24 | resolution = 1/16;
25 | % resolution = 1/4;
26 | disp(['Assuming resolution is ' num2str(resolution) ' degrees']);
27 |
28 | if ischar(extent)
29 | tmp1 = strsplit(extent, '.');
30 | extension = tmp1{2}; % this breaks if there is a '.' in the filename...
31 | if strcmp(extension, 'tif')
32 | disp('Subsetting to DEM');
33 | [dem, Rsub, lon_sub, lat_sub] = geotiffread2(extent);
34 | % dem = flipud(dem);
35 | % Rdemmat = georefobj2mat(Rsub, 'LL');
36 | % [lon_sub, lat_sub] = pixcenters(Rdemmat, size(dem));
37 | elseif strcmp(extension, 'shp')
38 | disp('Subsetting to shapefile');
39 | extent = shaperead(extent);
40 | shape_lons = extent.X(1:end-1)';
41 | shape_lats = extent.Y(1:end-1)';
42 | lon_sub = min(shape_lons):resolution:max(shape_lons);
43 | lat_sub = min(shape_lats):resolution:max(shape_lats);
44 |
45 | % min_lon = min(shape_lons);
46 | % max_lon = max(shape_lons);
47 | % min_lat = min(shape_lats);
48 | % max_lat = max(shape_lats);
49 | else
50 | error('Please make sure there is no . in the extent file name')
51 | end
52 |
53 | end
54 |
55 | if isnumeric(extent) % in case extent is bbox coordinates
56 | disp('Subsetting to bounding box');
57 | disp('Assuming resolution is 1/16 degrees');
58 | resolution = 1/16;
59 | lon_sub = extent(1):resolution:extent(2);
60 | lat_sub = extent(3):resolution:extent(4);
61 | end
62 |
63 | slat = soils(:,3);
64 | slon = soils(:,4);
65 | nlat = length(lat_sub);
66 | nlon = length(lon_sub);
67 |
68 | % lon = unique(slon);
69 | % lat = unique(slat);
70 | % lat_ind=find(lat>=min_lat & lat<=max_lat);
71 | % lon_ind=find(lon>=min_lon & lon<=max_lon);
72 | %
73 | % resolution = 1/16;
74 | % disp('Assuming resolution is 1/16 degrees')
75 | % lat_ind1 = find(abs(lat(:,1) - min_lat) < resolution/2);
76 | % lat_ind2 = find(abs(lat(:,1) - max_lat) < resolution/2);
77 | % lat_ind = lat_ind1:lat_ind2;
78 | % lon_ind1 = find(abs(lon(:,1) - min_lon) < resolution/2);
79 | % lon_ind2 = find(abs(lon(:,1) - max_lon) < resolution/2);
80 | % lon_ind = lon_ind1:lon_ind2;
81 |
82 | soils_subset = soils;
83 | soils_subset(:,1) = 0;
84 |
85 | % sind = zeros(nlon*nlat,1);
86 | % ind1 =1;
87 | for i=1:nlat
88 | for j=1:nlon
89 |
90 | % Get the index of the study area lat/lons that (nearly) matches the basin mask
91 | % sind(ind1) = find((abs(lat_sub(i) - slat) <= resolution/2) & (abs(lon_sub(j) - slon) <= resolution/2));
92 | sind = find((abs(lat_sub(i) - slat) <= resolution/2) & (abs(lon_sub(j) - slon) <= resolution/2));
93 |
94 |
95 | % figure
96 | % plotraster(lon_sub, lat_sub, dem, 'Basin Mask', 'Lon', 'Lat')
97 |
98 | % Adding this to ensure that cells outside of the domain are not
99 | % included in the subsetted soil parameter file (JRS 1/22/2020)
100 | if dem(i,j) == 0 || isnan(dem(i,j))
101 | continue
102 | end
103 |
104 | soils_subset(sind,1) = 1;
105 | % ind1=ind1+1;
106 |
107 | end
108 | disp(i)
109 | end
110 |
111 | soils_subset(soils_subset(:,1) == 0,:) = []; % include this line to reduce file size
112 | soil_var_path = fileparts(outname);
113 |
114 | if generate_tif
115 |
116 | soil_var_path = fullfile(soil_var_path, 'tifs');
117 | mkdir(soil_var_path)
118 | varnames = get_soil_var_names(setup); % 3L-no-org-frost-msds
119 | lat_vect = soils_subset(:,3);
120 | lon_vect = soils_subset(:,4);
121 |
122 | if length(varnames)~=size(soils_subset,2)
123 | error('Check that the value for setup is correct')
124 | end
125 |
126 | chopped = 0;
127 | for k=1:length(varnames)
128 | svar = soils_subset(:,k);
129 | svar_map = xyz2grid(lon_vect, lat_vect, svar);
130 |
131 | %%%%%%%------------------------------------------------
132 | % unless these figures are exactly the same, this function will not work as
133 | % expected
134 | % figure, imagesc(dem), title('DEM')
135 | % figure, imagesc(svar_map), title('Soil parameter')
136 | %%%%%%%------------------------------------------------
137 | if size(dem,1) ~= size(svar_map,1) || size(dem,2) ~= size(svar_map,2)
138 | disp('Matrix sizes do not match. Chopping off empty rows.')
139 | dem = dem(:,2:end);
140 | Rsub = makerefmat(min(lon_vect), min(lat_vect), resolution, resolution);
141 | chopped = 1;
142 | disp('Check whether the soil parameter plots are right-side up')
143 | disp('May need to flip them over for VIC model to run the correct domain')
144 | end
145 |
146 | soutname = fullfile(soil_var_path, [varnames{k} '.tif']);
147 |
148 | if chopped % difference most likely relates to Rsub
149 | geotiffwrite(soutname, svar_map, Rsub);
150 | else
151 | geotiffwrite(soutname, flipud(svar_map), Rsub);
152 | end
153 | end
154 | disp(['Geotiff files saved to ', soil_var_path]);
155 | end
156 |
157 | % figure, plotraster(lon_vect, lat_vect, elev_map, 'Elevation', '', '')
158 |
159 | ncells_in_spf = size(soils_subset,1);
160 | disp(['There are ' num2str(ncells_in_spf) 'cells in the subsetted soil parameter file'])
161 |
162 | write_soils(grid_decimal, soils_subset, outname, outformat)
163 |
164 | return
--------------------------------------------------------------------------------
/vicmatlab/soils/subset_soils2.m:
--------------------------------------------------------------------------------
1 | % Clips soil parameter file to basin extent
2 | %
3 | % INPUTS
4 | % soils: larger soil parameter file to subset from
5 | % maskfile: basin mask to subset to. Must have same resolution as soils.
6 | % outname: savename
7 | % outformat: livneh, 2l, or 3l
8 | % grid_decimal: e.g. 5
9 | % generate_tif: flag for whether or not to write tif files
10 | % setup: e.g. '3L-no-org-frost-msds'
11 | % resolution: e.g. 1/4 or 1/16
12 | %
13 | % OUTPUTS
14 | % soils_subset
15 | % soil_var_path
16 |
17 | function [soils_subset, soil_var_path] = subset_soils2(soils, maskfile, ...
18 | outname, outformat, grid_decimal, generate_tif, setup, resolution)
19 |
20 | [basinmask, Rsub, lon_sub, lat_sub] = geotiffread2(maskfile);
21 |
22 | slat = soils(:,3);
23 | slon = soils(:,4);
24 | nlat = length(lat_sub);
25 | nlon = length(lon_sub);
26 |
27 | large_mask = xyz2grid(slon, slat, soils(:,1));
28 | figure, plotraster(slon, slat, large_mask, 'mask');
29 |
30 | soils_subset = soils;
31 | soils_subset(:,1) = 0;
32 |
33 | X = basin_mask2coordinate_list(basinmask, Rsub);
34 | dt = delaunayTriangulation([slon, slat]);
35 | [inds, d] = nearestNeighbor(dt, X);
36 |
37 | soils_subset(inds,1) = 1;
38 | soils_subset(soils_subset(:,1) == 0,:) = []; % include this line to reduce file size
39 | soil_var_path = fileparts(outname);
40 |
41 | if length(unique(inds)) ~= length(inds)
42 | warning('The subset does not perfectly match the basin extent')
43 | warning('Consider adaptive measures, such as duplicating an adjacent cell')
44 |
45 | end
46 | %
47 | % % there can be duplicates in inds, causing soils_subset to be
48 | % % smaller than the mask. essentially, this is roundoff error,
49 | % % but we need to do something about it.
50 | %
51 | % % Find duplicates
52 | % [v, w] = unique( inds, 'stable' );
53 | % duplicate_indices = setdiff( 1:numel(inds), w );
54 | %
55 | % % Adds extra lines to soil parameter file to make sure it perfectly
56 | % % matches the input basinmask
57 | % numDup = length(duplicate_indices);
58 | %
59 | % % Put in grid cell (-87.625, 41.875) Found this by comparing maps.
60 | % % This cell is not in the domain, so I'll copy the next cell to it.
61 | % soils_subset(end + numDup,:) = soils(inds(duplicate_indices),:);
62 | % soils_subset(end,3) = 41.875; % the missing lat
63 | % soils_subset(end,4) = -87.625; % the missing lon
64 | %
65 | % end
66 |
67 | if generate_tif
68 |
69 | soil_var_path = fullfile(soil_var_path, 'tifs');
70 | mkdir(soil_var_path)
71 | varnames = get_soil_var_names(setup); % 3L-no-org-frost-msds
72 | lat_vect = soils_subset(:,3);
73 | lon_vect = soils_subset(:,4);
74 |
75 | if length(varnames)~=size(soils_subset,2)
76 | error('Check that the value for setup is correct')
77 | end
78 |
79 | chopped = 0;
80 | for k=1:length(varnames)
81 | svar = soils_subset(:,k);
82 | svar_map = xyz2grid(lon_vect, lat_vect, svar);
83 | % svar_map = flipud(svar_map);
84 | %
85 | % figure,plotraster(lon_vect, lat_vect, svar_map, '')
86 |
87 | % svar_map = xyz2grid(lon_vect, lat_vect, flipud(svar));
88 | % figure,plotraster(lon_vect, lat_vect, svar_map, '')
89 |
90 | %%%%%%%------------------------------------------------
91 | % unless these figures are exactly the same, this function will not work as
92 | % expected
93 | % figure, imagesc(basinmask), title('DEM')
94 | % figure, imagesc(svar_map), title('Soil parameter')
95 | %%%%%%%------------------------------------------------
96 |
97 | if size(basinmask,1) ~= size(svar_map,1) || size(basinmask,2) ~= size(svar_map,2)
98 | disp('Matrix sizes do not match. Chopping off empty rows.')
99 | basinmask = basinmask(:,2:end);
100 | Rsub = makerefmat(min(lon_vect), min(lat_vect), resolution, resolution);
101 | chopped = 1;
102 | disp('Check whether the soil parameter plots are right-side up')
103 | disp('May need to flip them over for VIC model to run the correct domain')
104 | end
105 |
106 | soutname = fullfile(soil_var_path, [varnames{k} '.tif']);
107 |
108 | if chopped % difference most likely relates to Rsub
109 | geotiffwrite(soutname, svar_map, Rsub);
110 | else
111 | geotiffwrite(soutname, flipud(svar_map), Rsub);
112 | end
113 | end
114 | disp(['Geotiff files saved to ', soil_var_path]);
115 | end
116 |
117 | % figure, plotraster(lon_vect, lat_vect, elev_map, 'Elevation', '', '')
118 |
119 | ncells_in_spf = size(soils_subset,1);
120 | disp(['There are ' num2str(ncells_in_spf) 'cells in the subsetted soil parameter file'])
121 |
122 | write_soils(grid_decimal, soils_subset, outname, outformat)
123 |
124 | return
--------------------------------------------------------------------------------
/vicmatlab/soils/upscale_soils.m:
--------------------------------------------------------------------------------
1 | % Upscale soils
2 | %
3 | % 9/11/2020 JRS
4 | % Upscales the VIC soil parameter file from its current resolution to a
5 | % coarser resolution
6 | %
7 | % INPUTS
8 |
9 | function [newsoils, newmask] = upscale_soils(soils, newres, oldres)
10 |
11 | % f = newres/oldres; % upscaling (or downscaling) factor
12 | [n, nvars] = size(soils); % n = original number of grid cells
13 |
14 | lat_vect = soils(:,3);
15 | lon_vect = soils(:,4);
16 |
17 | runcell = xyz2grid(lon_vect, lat_vect, soils(:,1));
18 | figure
19 | plotraster(lon_vect, lat_vect, runcell, 'Runcell');
20 |
21 | elev = xyz2grid(lon_vect, lat_vect, soils(:,22));
22 | figure
23 | plotraster(lon_vect, lat_vect, elev, 'Elev');
24 |
25 | [runcell2, newlons, newlats] = upscale_raster(runcell, lon_vect, lat_vect, newres, oldres, 'linear');
26 |
27 | figure
28 | plotraster(newlons, newlats, runcell2, 'Runcell');
29 |
30 | ncells_out = sum(runcell2(:));
31 | disp(['The number of cells in the output is ' num2str(ncells_out)])
32 |
33 | R = makerefmat(min(newlons), min(newlats), newres, newres);
34 | extent1 = basin_mask2coordinate_list(runcell2, R);
35 | lat = extent1(:,2); % output coordinates for soil parameter file
36 | lon = extent1(:,1);
37 |
38 | runcell3 = runcell2(:);
39 | runcell3(runcell3==0) = [];
40 | dat = [lat, lon, runcell3];
41 |
42 | runcell4 = xyz2grid(lon, lat, runcell3); % removes empty borders, if they exist
43 | figure,plotraster(lon, lat, runcell4,''); % check
44 |
45 | %% Assemble re-scaled soil parameter file
46 |
47 | newsoils = zeros(ncells_out, nvars);
48 | newsoils(:,1) = runcell3;
49 | newsoils(:,2) = 1:ncells_out;
50 |
51 | for k=5:nvars
52 |
53 | invar = xyz2grid(lon_vect, lat_vect, soils(:,k));
54 | outvar = upscale_raster(invar, lon_vect, lat_vect, newres, oldres, 'linear');
55 | % outvar = interp2(oldlats, oldlons, invar', newlats, newlons, 'linear')';
56 |
57 | % check
58 | % figure, plotraster(lons, lats, outvar,'');
59 | outvect = outvar(:);
60 |
61 | % lons(runcell2(:)==0) = [];
62 | % lats(runcell2(:)==0) = [];
63 | outvect(runcell2(:)==0) = [];
64 |
65 | % reconstruct = xyz2grid(lons, lats, outvect);
66 | % figure
67 | % plotraster(lons, lats, reconstruct, '');
68 |
69 | newsoils(:,k) = outvect;
70 |
71 | disp(['Processed soil variable number ' num2str(k) ' of ' num2str(nvars)])
72 | end
73 |
74 | lons = zeros(ncells_out,1);
75 | lats = zeros(ncells_out,1);
76 | ind = 1; % brute force fix for lat/lon not matching
77 | for i=1:length(newlons)
78 | for j=1:length(newlats)
79 | lons(ind) = newlons(i);
80 | lats(ind) = newlats(j);
81 | ind = ind + 1;
82 | end
83 | end
84 |
85 | tmpmask = runcell2(:);
86 | lats(tmpmask==0) = [];
87 | lons(tmpmask==0) = [];
88 | newsoils(:,3) = lats;
89 | newsoils(:,4) = lons;
90 |
91 | elev = xyz2grid(lons, lats, newsoils(:,22));
92 | figure
93 | plotraster(lons, lats, elev, 'elev')
94 |
95 | newmask = xyz2grid(lons, lats, newsoils(:,1));
96 | figure
97 | plotraster(lons, lats, newmask, 'elev')
98 |
99 | return
--------------------------------------------------------------------------------
/vicmatlab/soils/write_soil_moisture_to_spf.m:
--------------------------------------------------------------------------------
1 | % Write soil moisture to soil parameter file
2 | %
3 | % 8/18/2020 JRS
4 | % Writes initial soil moisture to soil parameter file, keeping
5 | % the correct spatial arrangement
6 | %
7 | % INPUTS
8 | % spf = name of soil parameter file
9 | % sm = soil moisture data
10 | % lon, lat = column vectors with lon, lat data for each grid cell
11 |
12 | function soils = write_soil_moisture_to_spf(spf, sm, lon, lat)
13 |
14 | soils = load(spf);
15 |
16 | slat = soils(:,3);
17 | slon = soils(:,4);
18 |
19 | T = delaunayn([slat, slon]);
20 | ncells = length(slon);
21 | disp(['There are ' num2str(ncells) ' grid cells'])
22 | for j=1:ncells
23 | k = dsearchn([lat, lon],T,[slat(j) slon(j)]);
24 | % disp(k)
25 | soils(j,19) = sm(k,1); % layer 1
26 | soils(j,20) = sm(k,2); % layer 2
27 | soils(j,21) = sm(k,3); % layer 3
28 | end
29 |
30 | outformat = '3l';
31 | precision = 5;
32 | write_soils(precision, soils, spf, outformat)
33 |
34 | return
--------------------------------------------------------------------------------
/vicmatlab/soils/write_soils.m:
--------------------------------------------------------------------------------
1 | % Write soils
2 | %
3 | % Writes out the soil parameter file
4 | %
5 | % INPUTS
6 | % precision = number of decimal points for the coordinates/forcing file
7 | % names
8 | % soils = data for soil parameter file
9 | % outname
10 | % outformat = livneh, 2l, or 3l
11 |
12 | function write_soils(precision, soils, outname, outformat)
13 |
14 | % Write out
15 | fstring = ['%.' num2str(precision) 'f'];
16 |
17 | if strcmp(outformat, 'livneh')
18 | % For the Livneh soil parameter file
19 | fspec = ['%d %d ' fstring ' ' fstring ' %.4f %.4f %.4f %.4f %d %.3f %.3f %.3f %.3f %.3f %.3f %d %d %d %.3f %.3f %.3f %.2f %.2f %.2f %.2f %d %d %.3f %.3f %.3f %.3f %.3f %.3f %.2f %.2f %.2f %.2f %.2f %.2f %d %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %d %d %d %d %d\n'];
20 | elseif strcmp(outformat, '2l')
21 | % For the 2-layer soil parameter file from HWSD
22 | fspec = ['%d %d ' fstring ' ' fstring ' ' '%.4f %.4f %.4f %.4f %d %.3f %.3f %.3f %.3f %d %d %.3f %.3f %.2f %.2f %.2f %d %d %.3f %.3f %.3f %.3f %.2f %.2f %.2f %.2f %d %.2f %.2f %.2f %.2f %.2f %.2f %d %d %d %d\n'];
23 | elseif strcmp(outformat, '3l')
24 | % This is used VIC-3L w no optional variables (54 columns in the soil parameter file).
25 | fspec = ['%d %d ' fstring ' ' fstring ' ' '%.4f %.4f %.4f %.4f %d %.3f %.3f %.3f %.3f %.3f %.3f %d %d %d %.3f %.3f %.3f %.2f %.2f %.2f %.2f %.2f %d %.3f %.3f %.3f %.3f %.3f %.3f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.4f %.4f %.2f %d %d %d %d %.2f\n'];
26 | else
27 | error('Please specify a valid value of outformat')
28 | end
29 |
30 | fID = fopen(outname, 'w');
31 | fprintf(fID, fspec, soils');
32 | fclose(fID);
33 | display(['Soils data saved to ' outname])
34 |
35 |
36 | return
--------------------------------------------------------------------------------
/vicmatlab/subsetting/_Example.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/vicmatlab/subsetting/_Example.pdf
--------------------------------------------------------------------------------
/vicmatlab/subsetting/basin_mask2coordinate_list.m:
--------------------------------------------------------------------------------
1 | % Obtains a list of coordinates from a basin mask
2 | %
3 | % The coordinates are all the points where the basin mask is not NaN.
4 | %
5 | % Example
6 | % maskname = '/Volumes/HD4/SWOTDA/Data/Colorado/colo_mask.tif';
7 | % coords = basin_mask2coordinate_list(maskname)
8 |
9 | function extent1 = basin_mask2coordinate_list(maskname)
10 |
11 | [basin_mask, R] = geotiffread2(maskname);
12 |
13 | basin_mask = double(basin_mask);
14 | basin_mask(basin_mask~=1) = NaN;
15 |
16 | ncells = length(basin_mask(~isnan(basin_mask)));
17 | [nx, ny] = size(basin_mask);
18 |
19 | k = 1;
20 | lon1 = zeros(ncells, 1);
21 | lat1 = zeros(ncells, 1);
22 | disp(['nx = ' num2str(nx)])
23 | for i=1:nx
24 | for j=1:ny
25 | if ~isnan(basin_mask(i,j))
26 | [lat1(k), lon1(k)] = pix2latlon(R, i, j);
27 | k = k + 1;
28 | end
29 | end
30 | if mod(i,100)==0
31 | disp(i)
32 | end
33 | end
34 |
35 | extent1 = [lon1, lat1];
36 |
37 | return
--------------------------------------------------------------------------------
/vicmatlab/subsetting/crop_dem.m:
--------------------------------------------------------------------------------
1 | % Crop DEM
2 | %
3 | % Crops a DEM to a user-defined extent
4 | %
5 | % INPUTS
6 | % demname = name of file containing DEM. Should be a GeoTIFF.
7 | % extent = [minlon, maxlon, minlat, maxlat]
8 | % outname = name of the output file (the cropped DEM)
9 | %
10 | % OUTPUTS
11 | % cropelev = cropped DEM
12 | % Rcrop = georeferencing matrix for the cropped DEM
13 | %
14 | % Sample inputs:
15 | % demname = '/Volumes/HD2/MERIT/DEM/Merged_1_16/merged_merit_dem_1_16.tif';
16 | % extent = [-121.5, -119, 37.5, 38.3];
17 | % outname = '/Volumes/HD4/SWOTDA/Data/Tuolumne/dem.tif';
18 |
19 | function [cropelev, Rcrop] = crop_dem(demname, extent, outname)
20 |
21 | [dem, R] = geotiffread(demname);
22 | dem = flipud(dem);
23 | Rmat = makerefmat(R.LongitudeLimits(1), R.LatitudeLimits(1), R.CellExtentInLongitude, R.CellExtentInLatitude);
24 | [lon, lat] = pixcenters(Rmat, size(dem));
25 |
26 | xres = R.CellExtentInLongitude;
27 | yres = R.CellExtentInLatitude;
28 |
29 | disp(['Bounding box is [' num2str(extent, 3) ']'])
30 |
31 | xmin = extent(1);
32 | xmax = extent(2);
33 | ymin = extent(3);
34 | ymax = extent(4);
35 |
36 | lat_range = [ymin ymax];
37 | lon_range = [xmin xmax];
38 |
39 | [rect, croplon, croplat] = make_cropping_rectangle(lon, lat, lon_range, lat_range, xres, yres);
40 | cropelev = imcrop(dem, rect);
41 |
42 | figure, subplot(1,2,1)
43 | plotraster(lon, lat, dem, 'Original elevation (m)', 'Lon', 'Lat')
44 | subplot(1,2,2)
45 | plotraster(croplon, croplat, cropelev, 'Cropped elevation (m)', 'Lon', 'Lat')
46 |
47 | Rcrop = makerefmat(min(croplon), min(croplat), xres, yres);
48 | geotiffwrite(outname, cropelev, Rcrop)
49 | disp(['Saved cropped DEM as ' outname])
50 |
51 | return
--------------------------------------------------------------------------------
/vicmatlab/subsetting/georefobj2mat.m:
--------------------------------------------------------------------------------
1 | % Georeferencing object to georeferencing matrix
2 | %
3 | % Written for latlon coordinates
4 | %
5 | % INPUTS
6 | % R = georeferencing object
7 | % type = "LL" or "center"
8 |
9 | function Rmat = georefobj2mat(R, type)
10 |
11 | xres = R.CellExtentInLongitude;
12 | yres = R.CellExtentInLatitude;
13 |
14 | switch type
15 | case 'LL'
16 | xmin = R.LongitudeLimits(1) + xres/2;
17 | ymin = R.LatitudeLimits(1) + yres/2;
18 | case 'center'
19 | xmin = R.LongitudeLimits(1);
20 | ymin = R.LatitudeLimits(1);
21 | otherwise
22 | disp('Please provide information about raster format')
23 | end
24 |
25 | Rmat = makerefmat(xmin, ymin, xres, yres);
26 |
27 |
28 | return
--------------------------------------------------------------------------------
/vicmatlab/subsetting/geotiffread2.m:
--------------------------------------------------------------------------------
1 | % Geotiffread2
2 | %
3 | % Modified version of geotiffread that returns lat and lon coordinates
4 |
5 | function [A, R, lon, lat] = geotiffread2(fname)
6 |
7 | try
8 | [A, ~, R] = geotiffread(fname);
9 | A = flipud(A);
10 | Rmat = georefobj2mat(R, 'LL');
11 | catch
12 | [A, R] = geotiffread(fname);
13 | A = flipud(A);
14 | Rmat = georefobj2mat(R, 'LL');
15 | end
16 |
17 | [lon, lat] = pixcenters(Rmat, size(A));
18 |
19 | % Remove no data values
20 | A(A < -1000) = NaN;
21 |
22 | return
--------------------------------------------------------------------------------
/vicmatlab/subsetting/get_soil_var_names.m:
--------------------------------------------------------------------------------
1 | % Get soil variable names
2 | %
3 | % Outputs the names of the columns in the soil parameter file, depending on
4 | % the model setup you wish to use
5 | %
6 | % setup = 2L, 2L-no-org-fs-july_tavg, 3L, 3L-no-org-frost-msds, livneh
7 |
8 | function varnames = get_soil_var_names(setup)
9 |
10 | switch setup
11 |
12 | case '2L'
13 |
14 | % Two-layer soil parameter file
15 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % all
16 | 'ws','c','expt1','expt2','ksat1','ksat2','phi_s1','phi_s2', ...
17 | 'init_moist1','init_moist2','elev','depth1','depth2','avg_T', ...
18 | 'dp','bubble1','bubble2','quartz1','quartz2','bulk_dens1','bulk_dens2', ...
19 | 'soil_dens1','soil_dens2','organic1','organic2','bdo1','bdo2','sdo1','sdo2', ...
20 | 'off_gmt','wcr_fract1','wcr_fract2','wpwp_fract1','wpwp_fract2','rough','snow_rough', ...
21 | 'annual_prec','resid_moist1','resid_moist2','fs_active','frost_slope','msds','july_Tavg'};
22 |
23 | case '2L-no-org-fs-july_tavg'
24 |
25 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % no organic, no frozen soil, no July_Tavg
26 | 'ws','c','expt1','expt2','ksat1','ksat2','phi_s1','phi_s2', ...
27 | 'init_moist1','init_moist2','elev','depth1','depth2','avg_T', ...
28 | 'dp','bubble1','bubble2','quartz1','quartz2','bulk_dens1','bulk_dens2', ...
29 | 'soil_dens1','soil_dens2', ...
30 | 'off_gmt','wcr_fract1','wcr_fract2','wpwp_fract1','wpwp_fract2','rough','snow_rough', ...
31 | 'annual_prec','resid_moist1','resid_moist2'};
32 |
33 | case '3L'
34 |
35 | % Three-layer soil parameter file (assuming top two layers are identical
36 | % given limited data)
37 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % all
38 | 'ws','c','expt1','expt2','expt3','ksat1','ksat2','ksat3','phi_s1','phi_s2','phi_s3', ...
39 | 'init_moist1','init_moist2','init_moist3','elev','depth1','depth2','depth3','avg_T', ...
40 | 'dp','bubble1','bubble2','bubble3','quartz1','quartz2','quartz3','bulk_dens1','bulk_dens2','bulk_dens3', ...
41 | 'soil_dens1','soil_dens2','soil_dens3','organic1','organic2','organic3','bdo1','bdo2','bdo3','sdo1','sdo2','sdo3', ...
42 | 'off_gmt','wcr_fract1','wcr_fract2','wcr_fract3','wpwp_fract1','wpwp_fract2','wpwp_fract3','rough','snow_rough', ...
43 | 'annual_prec','resid_moist1','resid_moist2','resid_moist3','fs_active','frost_slope','msds','july_Tavg'};
44 |
45 | case '3L-no-org-frost-msds'
46 |
47 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % three layers, no organic, no frost slope or msds
48 | 'ws','c','expt1','expt2','expt3','ksat1','ksat2','ksat3','phi_s1','phi_s2','phi_s3', ...
49 | 'init_moist1','init_moist2','init_moist3','elev','depth1','depth2','depth3','avg_T', ...
50 | 'dp','bubble1','bubble2','bubble3','quartz1','quartz2','quartz3','bulk_dens1','bulk_dens2','bulk_dens3', ...
51 | 'soil_dens1','soil_dens2','soil_dens3', ...
52 | 'off_gmt','wcr_fract1','wcr_fract2','wcr_fract3','wpwp_fract1','wpwp_fract2','wpwp_fract3','rough','snow_rough', ...
53 | 'annual_prec','resid_moist1','resid_moist2','resid_moist3','fs_active','july_Tavg'};
54 |
55 | case 'livneh'
56 |
57 | varnames = {'run_cell','grid_cell','lat','lon','b_infilt','ds','dsmax', ... % Livneh
58 | 'ws','c','expt1','expt2','expt3','ksat1','ksat2','ksat3','phi_s1','phi_s2','phi_s3', ...
59 | 'init_moist1','init_moist2','init_moist3','elev','depth1','depth2','depth3','avg_T', ...
60 | 'dp','bubble1','bubble2','bubble3','quartz1','quartz2','quartz3','bulk_dens1','bulk_dens2','bulk_dens3', ...
61 | 'soil_dens1','soil_dens2','soil_dens3', ...
62 | 'off_gmt','wcr_fract1','wcr_fract2','wcr_fract3','wpwp_fract1','wpwp_fract2','wpwp_fract3','rough','snow_rough', ...
63 | 'annual_prec','resid_moist1','resid_moist2','resid_moist3','fs_active'};
64 |
65 | otherwise
66 |
67 | disp('Please enter a valid option for setup')
68 |
69 | end
70 |
71 |
72 | return
--------------------------------------------------------------------------------
/vicmatlab/subsetting/grid2xyz.m:
--------------------------------------------------------------------------------
1 | function [x,y,z] = grid2xyz(Xgrid, Ygrid, Zgrid)
2 | %GRID2XYZ converts a grid to xyz and removes NaN's
3 | %
4 | % Syntax:
5 | % [x,y,z] = grid2xyz(Xgrid, Ygrid, Zgrid)
6 | %
7 | % Input:
8 | % Xgrid = x grid coordinates
9 | % Ygrid = y grid coordinates
10 | % Zgrid = z grid coordinates
11 | %
12 | % Output:
13 | % x = x coordinate (vector)
14 | % y = y coordinate (vector)
15 | % z = z coordinate (vector)
16 | %
17 | % Example
18 | % [x,y,z] = grid2xyz(Xgrid, Ygrid, Zgrid)
19 | %
20 | % See also
21 |
22 | %% Copyright notice
23 | % --------------------------------------------------------------------
24 | % Copyright (C) 2010 Alkyon Hydraulic Consultancy & Research
25 | % grasmeijerb
26 | %
27 | % bart.grasmeijer@alkyon.nl
28 | %
29 | % P.O. Box 248
30 | % 8300 AE Emmeloord
31 | % The Netherlands
32 | %
33 | % This library is free software: you can redistribute it and/or
34 | % modify it under the terms of the GNU Lesser General Public
35 | % License as published by the Free Software Foundation, either
36 | % version 2.1 of the License, or (at your option) any later version.
37 | %
38 | % This library is distributed in the hope that it will be useful,
39 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
40 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41 | % Lesser General Public License for more details.
42 | %
43 | % You should have received a copy of the GNU Lesser General Public
44 | % License along with this library. If not, see .
45 | % --------------------------------------------------------------------
46 |
47 | % This tool is part of OpenEarthTools.
48 | % OpenEarthTools is an online collaboration to share and manage data and
49 | % programming tools in an open source, version controlled environment.
50 | % Sign up to recieve regular updates of this function, and to contribute
51 | % your own tools.
52 |
53 | %% Version
54 | % Created: 05 Jul 2010
55 | % Created with Matlab version: 7.10.0.499 (R2010a)
56 |
57 | % $Id$
58 | % $Date$
59 | % $Author$
60 | % $Revision$
61 | % $HeadURL$
62 | % $Keywords: $
63 |
64 | %%
65 |
66 |
67 | %%%%%%%
68 | % modified by Jacob Schaperow to take a slightly different input
69 | if size(Xgrid,2) == 1
70 | [Xgrid, Ygrid] = meshgrid(Xgrid, Ygrid);
71 | end
72 | %%%%%%%
73 |
74 | x = reshape(Xgrid,[numel(Xgrid),1]);
75 | y = reshape(Ygrid,[numel(Ygrid),1]);
76 | z = reshape(Zgrid,[numel(Zgrid),1]);
77 | mynans = isnan(x) | isnan(y) | isnan(z);
78 | x(mynans) = [];
79 | y(mynans) = [];
80 | z(mynans) = [];
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/vicmatlab/subsetting/make_cropping_rectangle.m:
--------------------------------------------------------------------------------
1 | % Make cropping rectangle
2 | %
3 | % OUTPUTS
4 | % rect = cropping rectangle for imcrop
5 | % out_lon = longitude values for the cropping extent (vector)
6 | % out_lat = latitude values for the cropping extent (vector)
7 |
8 | function [rect, out_lon, out_lat, height, width] = make_cropping_rectangle(lon, lat, lon_range, lat_range, xres, yres)
9 |
10 | K = 4000; % parameter
11 | M = 50; % another parameter
12 |
13 | % must use grid cell centers for makerefmat
14 | R1 = makerefmat(min(lon), min(lat), xres, yres);
15 |
16 | % this formulation guarantees whole number indices
17 | % [ymin, xmin] = latlon2pix(R1, min(lat)+yres*10, min(lon)+xres*5) % lat, lon
18 |
19 | % find appropriate minimum values for the cropping rectangle
20 | minval_opt_1 = M;
21 | minval_opt_2 = M;
22 | for p=1:K
23 | tmp1 = abs(min(lon)+ p*xres - lon_range(1));
24 | tmp2 = abs(min(lat)+ p*yres - lat_range(1));
25 | if tmp1 < minval_opt_1
26 | minval_opt_1 = tmp1;
27 | p_opt_1 = p;
28 | end
29 | if tmp2 < minval_opt_2
30 | minval_opt_2 = tmp2;
31 | p_opt_2 = p;
32 | end
33 | end
34 | minlon = min(lon)+ p_opt_1*xres;
35 | minlat = min(lat)+ p_opt_2*yres;
36 |
37 | % make a 1-pixel border just to be safe
38 | minlon = minlon - xres;
39 | minlat = minlat - yres;
40 |
41 | % find appropriate maximum values for the cropping rectangle
42 | maxval_opt_1 = M;
43 | maxval_opt_2 = M;
44 | for p=1:K
45 | tmp1 = abs(minlon + p*xres - lon_range(2));
46 | tmp2 = abs(minlat + p*yres - lat_range(2));
47 | if tmp1 < maxval_opt_1
48 | maxval_opt_1 = tmp1;
49 | p_opt_1 = p;
50 | end
51 | if tmp2 < maxval_opt_2
52 | maxval_opt_2 = tmp2;
53 | p_opt_2 = p;
54 | end
55 | end
56 | maxlon = minlon + p_opt_1*xres;
57 | maxlat = minlat + p_opt_2*yres;
58 |
59 | % make a 1-pixel border just to be safe
60 | maxlon = maxlon + xres;
61 | maxlat = maxlat + yres;
62 |
63 | [ymin, xmin] = latlon2pix(R1, minlat, minlon);
64 | [ymax, xmax] = latlon2pix(R1, maxlat, maxlon);
65 | width = xmax - xmin;
66 | height = ymax - ymin;
67 |
68 | % rect = [floor(xmin), floor(ymin), ceil(width), ceil(height)];
69 | rect = [xmin, ymin, width, height];
70 |
71 | % I have to do this to get the code to work...
72 | height = height+1;
73 | width = width+1;
74 |
75 | out_lat = minlat:yres:maxlat;
76 | out_lon = minlon:xres:maxlon;
77 |
78 | return
79 |
80 |
81 |
--------------------------------------------------------------------------------
/vicmatlab/subsetting/prepb4_subset.R:
--------------------------------------------------------------------------------
1 | # File conversions before running subset_image_wrapper.m
2 | #
3 | # 6/5/2020 JRS
4 |
5 | library(raster)
6 |
7 | ut <- raster("/home/jschap/Documents/Codes/VICMATLAB/vicmatlab/subsetting/subset_image/upper_tuolumne_basin_merc.tif")
8 | ucrb <- raster("/home/jschap/Documents/ESSD/data/colo_mask.tif")
9 |
10 | ut
11 | ucrb[is.na(ucrb)] <- 0
12 | plot(ucrb)
13 |
14 | ut.wgs <- projectRaster(ut, crs = "+init=epsg:4326", method = "ngb", res = 1/16)
15 | origin(ut.wgs) <- c(0,0) # not great practice...
16 | writeRaster(ut.wgs, filename = "/home/jschap/Documents/Codes/VICMATLAB/vicmatlab/subsetting/subset_image/upper_tuolumne_basin_wgs.tif",
17 | overwrite = TRUE)
18 |
19 | # ut.wgs <- projectRaster(ut, crs = "+init=epsg:4326", method = "ngb", alignOnly = TRUE)
20 | # ut.wgs <- projectRaster(ut, ucrb, method = "ngb")
21 | # ut_extent <- projectExtent(ut, crs = "+init=epsg:4326")
22 | # ut.wgs <- crop(ut.wgs, ut_extent)
23 | #
24 | # plot(ut.wgs)
25 |
--------------------------------------------------------------------------------
/vicmatlab/subsetting/readme.txt:
--------------------------------------------------------------------------------
1 | This directory brings together all the VIC image mode subsetting files to make a unified approach to preparing inputs for the VIC image driver.
2 |
3 | /home/jschap/Documents/Codes/VICMATLAB/vicmatlab/subsetting/
4 | 1) subset_domain.m -- subsets the domain file
5 | 2) subset_parameter.m -- subsets the parameter file, requires a ton of RAM and doesn't always work
6 | 3) subset_netcdf_w_geotiffmask.m -- subsets a NetCDF file to a (geotiff) mask
7 |
8 | /home/jschap/Documents/Codes/VICMATLAB/vicmatlab/utility/
9 | 4) classic2image.m -- converts the L2013/L2015 VIC classic parameter files to NetCDF format for the image driver. Does not do subsetting.
10 |
11 | /home/jschap/Documents/ESSD/codes/
12 | 5) subset_vicglobal_to_extent.m -- wrapper for subsetting the image mode VICGlobal parameters (converted from Classic parameters using Dongyue's classic to image converter) to the basin mask. Would be nice to generalize so it would work with the BV2019 parameters (currently, it gives an error). Calls subset_parameter.m
13 |
14 | /home/jschap/Documents/Codes/VICMATLAB/vicmatlab/forcings/
15 | 6) write_netcdf_forcing.m -- converts ASCII forcing data to NetCDF forcings
16 | 7) make_netcdf_forcing.m -- converts ASCII forcing data to NetCDF forcings. Only handles one year. Other versions are probably better.
17 | 8) convert_forcing.m -- converts ASCII forcing data to NetCDF forcings
18 |
19 | /home/jschap/Documents/ESSD/codes/Old/
20 | 9) subset_netcdf_to_bb.R -- subsets a NetCDF file to a basin boundary. Intended for use with VIC image driver output files.
21 |
22 | Desired functionality:
23 | Given classic mode parameter files and a geotiff or shapefile with the basin mask, convert the classic mode inputs to image mode and subset them to the domain.
24 | Subset ASCII forcings to the domain and convert them to NetCDF format
25 | Ideally works with VICGlobal, L2013, and BV2019 inputs.
26 |
27 | Minimum functionality:
28 | Subset image mode parameters to the domain
29 | Convert image mode forcing files to NetCDF format
30 |
31 |
--------------------------------------------------------------------------------
/vicmatlab/subsetting/subset_domain.m:
--------------------------------------------------------------------------------
1 | % Subset domain
2 | %
3 | % Function for subsetting the VIC 5 image mode domain file
4 | %
5 | % INPUTS
6 | % Extent = study area extent. Can input either a shapefile or a list of latlon coordinates
7 | % global_domain = name of the input domain file you wish to subset`
8 | % outname = name of the output, subsetted domain file
9 | %
10 | % OUTPUTS
11 | % Subsetted domain file for the VIC 5 image driver
12 | %
13 | % Sample inputs:
14 | % extent = horzcat([-121.5942; -118.9067], [37.40583; 38.40583]);
15 | % global_domain = '/Volumes/HD3/VICParametersGlobal/Global_1_16/v1_3/VICGlobal_domain.nc';
16 | % outname = '/Volumes/HD4/SWOTDA/Data/Tuolumne/domain_sub.nc';
17 |
18 | function outname = subset_domain(basinmaskname, global_domain, outname)
19 |
20 | extent = basin_mask2coordinate_list(basinmaskname);
21 | basinmask = geotiffread2(basinmaskname);
22 |
23 | % Read coordinates for full domain
24 | lat = ncread(global_domain,'lat');
25 | lon = ncread(global_domain,'lon');
26 |
27 | % if ischar(extent)
28 | % tmp1 = strsplit(extent, '.');
29 | % extension = tmp1{2};
30 | % if strcmp(extension, 'shp')
31 | % disp('Input is a shapefile');
32 | % extent = shaperead(extent);
33 | % lon_sub = extent.X(1:end-1)';
34 | % lat_sub = extent.Y(1:end-1)';
35 | %
36 | % % resolution = 1/16;
37 | % % disp('Assuming resolution is 1/16 degrees')
38 | % % lon_sub = min(lon_sub):resolution:max(lon_sub);
39 | % % lat_sub = min(lat_sub):resolution:max(lat_sub);
40 | %
41 | % else
42 | % disp('Please input extent as a shapefile or a list of coordinates')
43 | % end
44 | % end
45 |
46 | if isnumeric(extent)
47 | lon_sub = extent(:,1);
48 | lat_sub = extent(:,2);
49 | disp('Input is a list of coordinates');
50 | end
51 |
52 | min_lat=min(lat_sub);
53 | max_lat=max(lat_sub);
54 | min_lon=min(lon_sub);
55 | max_lon=max(lon_sub);
56 |
57 | % inclusive (larger domain)
58 | % % exclusive (smaller domain)
59 | inclusive = 1;
60 | if inclusive
61 | disp('Using inclusive option. Both options seem to work.')
62 | resolution = 1/16;
63 | disp('Assuming resolution is 1/16 degrees')
64 | lat_ind1 = find(abs(lat(:,1) - min_lat) <= resolution/2);
65 | lat_ind2 = find(abs(lat(:,1) - max_lat) <= resolution/2);
66 | lat_ind = lat_ind1:lat_ind2;
67 | lon_ind1 = find(abs(lon(:,1) - min_lon) <= resolution/2);
68 | lon_ind2 = find(abs(lon(:,1) - max_lon) <= resolution/2);
69 | lon_ind = lon_ind1:lon_ind2;
70 | else
71 | % Need to have lat/lon values on the same grid
72 | lat_ind = find(lat(:,1)>=min_lat & lat(:,1)<=max_lat);
73 | lon_ind = find(lon(:,1)>=min_lon & lon(:,1)<=max_lon);
74 | end
75 |
76 | if isempty(lat_ind)
77 | disp('empty lat ind')
78 | outname = 'none';
79 | return
80 | end
81 |
82 | % ##########################################################################
83 |
84 | % 1-D array
85 | % two possible conventions: [lons, lats] or [lon, lat]
86 | lats = 0; % flag for name of variable
87 | if lats
88 | var_list1={'lats','lons'};
89 | else
90 | var_list1={'lat','lon'};
91 | end
92 | nccreate(outname,'lat','Datatype','double',...
93 | 'Dimensions',{'lat',length(lat_ind)},'Format','netcdf4_classic')
94 | nccreate(outname,'lon','Datatype','double',...
95 | 'Dimensions',{'lon',length(lon_ind)},'Format','netcdf4_classic')
96 | ncwrite(outname,'lat',lat(lat_ind));
97 | ncwrite(outname,'lon',lon(lon_ind));
98 |
99 | % 2-D matrices
100 | var_list_3 = {'mask'};
101 | var_in = [];
102 | var_in=ncread(global_domain,var_list_3{1});
103 |
104 | % var_in
105 | % basinmask
106 | % temp = var_in(lon_ind,lat_ind);
107 | % var_list_3{1} = basinmask';
108 |
109 | % eval([var_list_3{1},'=var_in(lon_ind,lat_ind);']);
110 |
111 | nccreate(outname,var_list_3{1},...
112 | 'Datatype','int32',...
113 | 'Dimensions',{'lon',length(lon_ind),'lat',length(lat_ind)},...
114 | 'Format','netcdf4_classic')
115 |
116 | use_mask = 1;
117 | if use_mask
118 | disp('using basin mask')
119 | ncwrite(outname,var_list_3{1}, basinmask');
120 | else
121 | disp('not using basin mask')
122 | disp('but mask is still applied for frac and area')
123 | ncwrite(outname,var_list_3{1}, ones(size(basinmask')));
124 | end
125 |
126 | var_list2={'frac','area'};
127 | for i=1:length(var_list2)
128 | var_in=[];
129 | var_in=ncread(global_domain,var_list2{i});
130 | eval([var_list2{i},'=var_in(lon_ind,lat_ind);']);
131 |
132 | nccreate(outname,var_list2{i},...
133 | 'Datatype','double',...
134 | 'Dimensions',{'lon',length(lon_ind),'lat',length(lat_ind)},...
135 | 'Format','netcdf4_classic')
136 | ncwrite(outname,var_list2{i},eval(var_list2{i}));
137 | end
138 |
139 | return
140 |
--------------------------------------------------------------------------------
/vicmatlab/subsetting/subset_image_wrapper.m:
--------------------------------------------------------------------------------
1 | %% Image mode
2 |
3 | % Subset Image
4 | %
5 | % Wrapper for subsetting the global VIC parameter file
6 | % to a user-specified domain
7 | %
8 | % There are different codes to use for different parameter sets
9 | % For VICGlobal, use subset_domain and subset_parameter
10 | % For L2013, use classic2image
11 | % For BV2019, use subset_domain and subset_parameter
12 |
13 | addpath(genpath('/home/jschap/Documents/Codes/VICMATLAB/vicmatlab'))
14 | outdir = '/home/jschap/Documents/Codes/VICMATLAB/vicmatlab/subsetting/subset_image/';
15 | basinname = 'ucrb';
16 |
17 | %% Specify extent
18 |
19 | % Input may be a shapefile or a list of coordinates
20 | % The coordinate system must have the same resolution, origin, and CRS as
21 | % the image mode parameter files that you are subsetting.
22 |
23 | ucrb_shp = '/home/jschap/Documents/ESSD/data/bb.shp';
24 | ucrb_tif = '/home/jschap/Documents/ESSD/data/colo_mask.tif';
25 | tuolumne_tif = '/home/jschap/Documents/Codes/VICMATLAB/vicmatlab/subsetting/subset_image/upper_tuolumne_basin_wgs.tif';
26 |
27 | % If you want to use a basin mask (geotiff), you must get a list of coords
28 | % basin_coords = basin_mask2coordinate_list(ucrb_tif);
29 |
30 | %% Subset BV2019
31 |
32 | % BV2019
33 | bv2019domain = '/media/jschap/HD_ExFAT/vicglobal-image-mode-inputs/VICGlobal_domain.nc';
34 | bv2019params = '/home/jschap/Documents/Data/BV2019/params.CONUS_MX.MOD_IGBP.mode.2000_2016.nc';
35 | subset_domain(ucrb_tif, bv2019domain, fullfile(outdir, [basinname, '_bv2019_domain.nc']));
36 | subset_parameter(ucrb_tif, bv2019params, fullfile(outdir, [basinname, '_bv2019_params.nc']));
37 |
38 | %% Subset L2013
39 |
40 | % L2013
41 | % Convert Classic mode inputs to image mode and do subsetting in one step
42 | % The subsetting is controlled by the forcings, so they need to be subset
43 | % to the domain first.
44 | %
45 | % NEEDS WORK
46 |
47 | parpath = '/home/jschap/Documents/Data/VICParametersCONUS/';
48 | inputs.veglib = fullfile(parpath, 'vic_veglib_nohead.txt');
49 | inputs.soilparfile = fullfile(parpath, 'vic.soil.0625.new.cal.adj.conus.plus.crb.can_no_July_T_avg.txt');
50 | inputs.snowband = fullfile(parpath, 'vic.snow.0625.new.cal.adj.can.5bands');
51 | inputs.vegparam = fullfile(parpath, 'vic.veg.0625.new.cal.adj.can');
52 |
53 | % Forcings
54 | inputs.forcdir = '/media/jschap/HD_ExFAT/ucrb/disagg_forcings_L13_clip/full_data*';
55 | inputs.domainfile_name = fullfile(outdir, [basin_name, '_domain.nc']);
56 | inputs.params_name = fullfile(outdir, [basin_name, '_params.nc']);
57 | subset_forcings
58 | subset_forcings_to_spf
59 | classic2image()
60 |
61 | %% Subset VICGlobal
62 |
63 | % VICGlobal
64 | vicglobaldomain = '/media/jschap/HD_ExFAT/vicglobal-image-mode-inputs/VICGlobal_domain.nc';
65 | vicglobalparams = '/media/jschap/HD_ExFAT/vicglobal-image-mode-inputs/VICGlobal_params.nc';
66 | subset_domain(basin_coords, l2013domain, fullfile(outdir,' upper_tuolumne_domain.nc'))
67 |
68 | %% Aggregate forcings (if desired)
69 |
70 | forcdir = '/media/jschap/HD_ExFAT/ucrb/disagg_forcings_L13_clip';
71 | delt_in = 1; % hours
72 | delt_out = 6; % hours
73 | starttime = datetime(1980, 1, 1, 0, 0, 0);
74 | outdir = '/media/jschap/HD_ExFAT/ucrb/L13_forc_6hr_ucrb';
75 | precip_col = 1; % need to specify because precip is summed, not averaged,
76 | % to keep units consistant (mm/timestep)
77 | hpc = 1;
78 | [aggf, aggt] = aggregate_forcing(forcdir, delt_in, delt_out, starttime, outdir, precip_col, hpc);
79 | % ^^^ takes about 2 hours to run, makes about 20 GB of output data
80 |
81 | %% Convert forcings
82 |
83 | forcdir = '/media/jschap/HD_ExFAT/ucrb/L13_forc_6hr_ucrb';
84 | outname_domain = fullfile('/media/jschap/HD_ExFAT/ucrb/L13_forc_6hr_ucrb_nc', basinname);
85 | start_date = datetime(1980, 1, 1, 0, 0, 0); % need to specify hours
86 | end_date = date
87 | time(2011, 12, 31, 23, 0, 0);
88 | nt_per_day = 4;
89 | prefix = 'full_data_';
90 | precision = 5;
91 | convert_forcing(forcdir, prefix, outname_domain, precision, start_date, end_date, nt_per_day)
92 | % ^^ takes 23 minutes per year for the UCRB (7833 grid cells)
93 |
94 | %%
95 |
96 |
97 | % Define extent
98 | % extent = horzcat([75; 76], [34; 35]);
99 | extent = '/Users/jschap/Documents/Research/SWOTDA_temp/Tuolumne/Tuolumne2/Shapefiles/upper_tuolumne.shp';
100 | % extent = horzcat([-85.5625; -97.6875], [36.625; 48.0625]);
101 | % extent = horzcat([65; 85], [23; 38]);
102 |
103 | % Subset domain
104 | global_domain = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1_5/Image/VICGlobal_domain.nc';
105 | outname_domain = '/Volumes/HD4/SWOTDA/Data/Tuolumne/v1_7/Image_VG/tuo_domain.nc';
106 | subset_domain(extent, global_domain, outname_domain)
107 |
108 | % Subset parameters
109 | global_params = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1_5/Image/VICGlobal_params.nc';
110 | % outname_params = '/Volumes/HD4/SWOTDA/Data/Tuolumne/v1_4/Image_VICGlobal/params_subL.nc';
111 | outname_params = '/Volumes/HD4/SWOTDA/Data/Tuolumne/v1_7/Image_VG/tuo_params.nc';
112 | subset_parameter(extent, global_params, outname_params)
113 |
114 | % takes a long time to run (took a couple hours for the Tuolumne basin test case)
115 | % also uses a lot of RAM, like 20 GB
--------------------------------------------------------------------------------
/vicmatlab/subsetting/subset_netcdf_w_geotiffmask.m:
--------------------------------------------------------------------------------
1 | % Subsets a netCDF file using a geotiff mask
2 | %
3 | % Example: subsetting VIC Image Driver outputs to a particular study basin
4 | % or subsetting NetCDF forcing files to a particular study basin. Based on
5 | % vicinputworkflow.m code
6 | %
7 | % runoff_tuolumne = subset_netcdf_w_geotiffmask(runoff_livneh, livneh_lon, livneh_lat, dem_tuo.tif)
8 | %
9 | % Modified so it actually works. But only for one time step. Multi-temporal
10 | % still needs to be implemented.
11 |
12 | function [cropvar, cropped_lon, cropped_lat] = subset_netcdf_w_geotiffmask(nc_data, nc_lon, nc_lat, mask_lon, mask_lat, mask1)
13 |
14 | [~, ~, nt] = size(nc_data);
15 | [ny, nx] = size(mask1);
16 |
17 | % This could be made more efficient vvvvv
18 | % [mask1, R1, ~, ~] = geotiffread2(geotiff_mask);
19 | % R1mat = georefobj2mat(R1, 'LL');
20 | % [masklon1, masklat1] = pixcenters(R1mat, size(mask1));
21 | % [masklon, masklat, maskvals] = grid2xyz(masklon1', masklat1', mask1);
22 |
23 | nanmask = double(mask1);
24 | nanmask(nanmask==0) = NaN;
25 |
26 | figure, subplot(1,2,1)
27 | plotraster(nc_lon, nc_lat, nc_data, 'Input data', '', '')
28 | caxis([0, 300])
29 | subplot(1,2,2)
30 | plotraster(mask_lon, mask_lat, nanmask, 'Mask', '', '')
31 |
32 | minx = min(mask_lon);
33 | miny = min(mask_lat);
34 | maxx = max(mask_lon);
35 | maxy = max(mask_lat);
36 | extent = [minx, maxx, miny, maxy];
37 | demname = 'temp1.tif';
38 | outname = 'temp2.tif';
39 | xres = 1/16;
40 | yres = 1/16;
41 | R = makerefmat(min(nc_lon), min(nc_lat), xres, yres);
42 |
43 | geotiffwrite(demname, nc_data(:,:,1), R);
44 |
45 | % This does not give an exact match to the size of the original mask,
46 | % so it is not useful.
47 | [cropvar, Rcrop] = crop_dem(demname, extent, outname);
48 |
49 | [cropped_lon, cropped_lat] = pixcenters(Rcrop, size(cropvar));
50 |
51 | verbose = 1;
52 | if verbose
53 | disp('Ignore title of plot -- it was originally intended for cropping a DEM')
54 | end
55 |
56 |
57 |
58 | % demname = '/Volumes/HD2/MERIT/DEM/Merged_1_16/merged_merit_dem_1_16.tif';
59 | % extent = [-121.5, -119, 37.5, 38.3];
60 | % outname = '/Volumes/HD4/SWOTDA/Data/Tuolumne/dem.tif';
61 |
62 | % ncells = length(nanmask(:));
63 | % lat_ind = zeros(ncells,1);
64 | % lon_ind = zeros(ncells,1);
65 | % k = 1;
66 | % for i=1:nx
67 | % for j=1:ny
68 | % [~, lat_ind(k)] = min(abs(mask_lat(i) - nc_lat));
69 | % [~, lon_ind(k)] = min(abs(mask_lon(j) - nc_lon));
70 | % k = k + 1;
71 | % end
72 | % end
73 | %
74 | % B = NaN(nt, ncells); % the subsetted data
75 | % for k=1:ncells
76 | % B(:,k) = nc_data(lon_ind(k),lat_ind(k), :);
77 | % end
78 | %
79 | % x_sub = zeros(ncells, 1);
80 | % y_sub = zeros(ncells, 1);
81 | % for k=1:ncells
82 | % x_sub(k) = nc_lon(lon_ind(k));
83 | % y_sub(k) = nc_lat(lat_ind(k));
84 | % end
85 | %
86 | % B_map = xyz2grid(x_sub, y_sub, B');
87 | % figure, plotraster(mask_lon, mask_lat, B_map, '', '', '')
88 | %
89 | % % Need to account for mask
90 | % % Cells that are not in the mask should not be counted toward ncells
91 | % masklon(maskvals==0) = [];
92 | % masklat(maskvals==0) = [];
93 | % ncells = length(masklon);
94 | %
95 | % figure
96 | % plotraster(masklon, flipud(masklat), mask1, '', '','')
97 | %
98 | % figure
99 | % plotraster(nc_lon, nc_lat, flipud(nc_data), '', '','')
100 | %
101 | %
102 | % % The above only has to be done once
103 | % % ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
104 | %
105 | % B = NaN(nt, ncells); % the subsetted data
106 | % for k=1:ncells
107 | % B(:,k) = nc_data(lon_ind(k),lat_ind(k), :);
108 | % end
109 |
110 | return
--------------------------------------------------------------------------------
/vicmatlab/subsetting/subset_soils.m:
--------------------------------------------------------------------------------
1 | % Clips soil parameter file to basin extent
2 | %
3 | % INPUTS
4 | % soils = soil parameter file encompassing a region at least as large as the basin
5 | % landmask = land mask used to generate the soil parameter file
6 | % extent = bounding box or shapefile for subsetting
7 | % outname = Name of output
8 | % outformat = format of output ('3l'). See write_soils.m
9 | % grid_decimal = precision used in forcing filenames
10 | %
11 | % OUTPUTS
12 | % Clipped soil parameter file
13 | %
14 | % Modified 1/22/2020 JRS
15 | % Does a somewhat better job subsetting to a basin mask/matching the extent of the
16 | % basin mask
17 |
18 | function [soils_subset, soil_var_path] = subset_soils(soils, extent, outname, outformat, grid_decimal, generate_tif, setup)
19 |
20 | disp('Assuming resolution is 1/16 degrees');
21 | resolution = 1/16;
22 |
23 | if ischar(extent)
24 | tmp1 = strsplit(extent, '.');
25 | extension = tmp1{2}; % this breaks if there is a '.' in the filename...
26 | if strcmp(extension, 'tif')
27 | disp('Subsetting to DEM');
28 | [dem, Rsub, lon_sub, lat_sub] = geotiffread2(extent);
29 | % dem = flipud(dem);
30 | % Rdemmat = georefobj2mat(Rsub, 'LL');
31 | % [lon_sub, lat_sub] = pixcenters(Rdemmat, size(dem));
32 | elseif strcmp(extension, 'shp')
33 | disp('Subsetting to shapefile');
34 | extent = shaperead(extent);
35 | shape_lons = extent.X(1:end-1)';
36 | shape_lats = extent.Y(1:end-1)';
37 | lon_sub = min(shape_lons):resolution:max(shape_lons);
38 | lat_sub = min(shape_lats):resolution:max(shape_lats);
39 |
40 | % min_lon = min(shape_lons);
41 | % max_lon = max(shape_lons);
42 | % min_lat = min(shape_lats);
43 | % max_lat = max(shape_lats);
44 | else
45 | error('Please make sure there is no . in the extent file name')
46 | end
47 |
48 | end
49 |
50 | if isnumeric(extent) % in case extent is bbox coordinates
51 | disp('Subsetting to bounding box');
52 | disp('Assuming resolution is 1/16 degrees');
53 | resolution = 1/16;
54 | lon_sub = extent(1):resolution:extent(2);
55 | lat_sub = extent(3):resolution:extent(4);
56 | end
57 |
58 | slat = soils(:,3);
59 | slon = soils(:,4);
60 | nlat = length(lat_sub);
61 | nlon = length(lon_sub);
62 |
63 | % lon = unique(slon);
64 | % lat = unique(slat);
65 | % lat_ind=find(lat>=min_lat & lat<=max_lat);
66 | % lon_ind=find(lon>=min_lon & lon<=max_lon);
67 | %
68 | % resolution = 1/16;
69 | % disp('Assuming resolution is 1/16 degrees')
70 | % lat_ind1 = find(abs(lat(:,1) - min_lat) < resolution/2);
71 | % lat_ind2 = find(abs(lat(:,1) - max_lat) < resolution/2);
72 | % lat_ind = lat_ind1:lat_ind2;
73 | % lon_ind1 = find(abs(lon(:,1) - min_lon) < resolution/2);
74 | % lon_ind2 = find(abs(lon(:,1) - max_lon) < resolution/2);
75 | % lon_ind = lon_ind1:lon_ind2;
76 |
77 | soils_subset = soils;
78 | soils_subset(:,1) = 0;
79 |
80 | % sind = zeros(nlon*nlat,1);
81 | % ind1 =1;
82 | for i=1:nlat
83 | for j=1:nlon
84 |
85 | % Get the index of the study area lat/lons that (nearly) matches the basin mask
86 | % sind(ind1) = find((abs(lat_sub(i) - slat) <= resolution/2) & (abs(lon_sub(j) - slon) <= resolution/2));
87 | sind = find((abs(lat_sub(i) - slat) <= resolution/2) & (abs(lon_sub(j) - slon) <= resolution/2));
88 |
89 | % figure
90 | % plotraster(lon_sub, lat_sub, dem, 'Basin Mask', 'Lon', 'Lat')
91 |
92 | % Adding this to ensure that cells outside of the domain are not
93 | % included in the subsetted soil parameter file (JRS 1/22/2020)
94 | if dem(i,j) == 0 || isnan(dem(i,j))
95 | continue
96 | end
97 |
98 | soils_subset(sind,1) = 1;
99 | % ind1=ind1+1;
100 |
101 | end
102 | disp(i)
103 | end
104 |
105 | soils_subset(soils_subset(:,1) == 0,:) = []; % include this line to reduce file size
106 | soil_var_path = fileparts(outname);
107 |
108 | if generate_tif
109 | varnames = get_soil_var_names(setup);
110 | lat_vect = soils_subset(:,3);
111 | lon_vect = soils_subset(:,4);
112 |
113 | if length(varnames)~=size(soils_subset,2)
114 | error('Check that the value for setup is correct')
115 | end
116 |
117 | for k=1:length(varnames)
118 | svar = soils_subset(:,k);
119 | svar_map = xyz2grid(lon_vect, lat_vect, svar);
120 |
121 | %%%%%%%------------------------------------------------
122 | % unless these figures are exactly the same, this function will not work as
123 | % expected
124 | % figure, imagesc(dem), title('DEM')
125 | % figure, imagesc(svar_map), title('Soil parameter')
126 | %%%%%%%------------------------------------------------
127 |
128 | soutname = fullfile(soil_var_path, [varnames{k} '.tif']);
129 | geotiffwrite(soutname, flipud(svar_map), Rsub);
130 | end
131 | disp(['Geotiff files saved to ', soil_var_path]);
132 | end
133 |
134 | % figure, plotraster(lon_vect, lat_vect, elev_map, 'Elevation', '', '')
135 |
136 | ncells_in_spf = size(soils_subset,1);
137 | disp(['There are ' num2str(ncells_in_spf) 'cells in the subsetted soil parameter file'])
138 |
139 | write_soils(grid_decimal, soils_subset, outname, outformat)
140 |
141 | return
--------------------------------------------------------------------------------
/vicmatlab/subsetting/subset_soils_to_coords.m:
--------------------------------------------------------------------------------
1 | % Subset soils to coords
2 | %
3 | % Subset soil parameter file to a list of coordinates
4 | % 2/28/2021 JRS
5 |
6 | % coordinates = [lon, lat];
7 |
8 | function soils_sub = subset_soils_to_coords(soils, coordinates, outname)
9 |
10 | resolution = 1/16;
11 | grid_decimal = 5;
12 | outformat = '3l';
13 |
14 | % Find lines in SPF that are closest to each line of the coordinate list
15 | % In future, make match_coords.m to do this task
16 |
17 | slat = soils(:,3);
18 | slon = soils(:,4);
19 |
20 | soils_sub = soils;
21 | soils_sub(:,1) = 0;
22 |
23 | ncoords = size(coordinates,1);
24 | for k=1:ncoords
25 | lon1 = coordinates(k,1);
26 | lat1 = coordinates(k,2);
27 | sind = find((abs(lat1 - slat) <= resolution/2) & (abs(lon1 - slon) <= resolution/2));
28 | soils_sub(sind,1) = 1;
29 | end
30 |
31 | soils_sub(soils_sub(:,1) == 0,:) = []; % include this line to reduce file size
32 |
33 | ncells_in_spf = size(soils_sub,1);
34 | disp(['There are ' num2str(ncells_in_spf) 'cells in the subsetted soil parameter file'])
35 |
36 | write_soils(grid_decimal, soils_sub, outname, outformat)
37 |
38 | return
39 |
--------------------------------------------------------------------------------
/vicmatlab/subsetting/subset_wrapper.m:
--------------------------------------------------------------------------------
1 | % Wrapper
2 | %
3 | % Wrapper for subsetting the VICGlobal input files to a particular area of interest
4 | % The VICGlobal subsetting functions require the image processing toolbox.
5 |
6 | % Not necessary, but we will run this from within its own directory
7 | addpath('/home/jschap/Documents/Codes/VICMATLAB/vicmatlab/subsetting/')
8 | % cd('/Users/jschap/Documents/Codes/VICMATLAB/Subsetting/Subsetting')
9 | clearvars -except soils_vg soils
10 |
11 | %% Classic mode: Subsets the soil parameter file.
12 |
13 | % Load soil parameter file
14 | soilfile = '/Volumes/HD3/VICParametersCONUS/vic.soil.0625.new.cal.adj.conus.plus.crb.can_no_July_T_avg.txt';
15 | % soilfile = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1_5/Classic/soils_3L_MERIT.txt';
16 | disp('Loading soil parameter file')
17 | % soils_vg = load(soilfile);
18 | soils = load(soilfile);
19 | disp('Soil parameter file has been loaded')
20 |
21 | % Define extent
22 | % extent = [75, 76, 34, 35];
23 | extent = '/Volumes/HD4/SWOTDA/Data/Colorado/colo_mask.tif';
24 | % extent = '/Users/jschap/Documents/Research/Glaciers/Skagit/skagit_mask.tif';
25 | % extent = '/Volumes/HD4/SWOTDA/Data/IRB/VIC/dem.tif';
26 | % use full name; do not use . in file name
27 | % extent = './Data/IRB/VIC/34N_75E/dem.tif';
28 | % extent = '/Volumes/HD4/SWOTDA/Data/UMRB/dem.tif'; % UMRB
29 |
30 | grid_decimal = 5; % number of decimals used in forcing filenames
31 | % outformat = '3l';
32 | outformat = 'livneh'; % format of input soil parameter file (number of soil layers)
33 | outname = '/Volumes/HD4/SWOTDA/Data/Colorado/colo_soils_L15.txt';
34 | % outname = '/Volumes/HD4/SWOTDA/Data/IRB/VIC/Classic/soils_.txt';
35 | % outname = '/Volumes/HD4/SWOTDA/Data/UMRB/soils_umrb_vg.txt';
36 | % outname = '/Users/jschap/Documents/Research/Glaciers/Skagit/skagit_soils.txt';
37 |
38 | soils_subset = subset_soils(soils, extent, outname, outformat, grid_decimal, generate_tif, setup);
39 |
40 | %% Image mode
41 |
42 | % Subset Image
43 | %
44 | % Wrapper for subsetting the global VIC parameter file
45 | % to a user-specified domain
46 |
47 | % Define extent
48 | % extent = horzcat([75; 76], [34; 35]);
49 | extent = '/Users/jschap/Documents/Research/SWOTDA_temp/Tuolumne/Tuolumne2/Shapefiles/upper_tuolumne.shp';
50 | % extent = horzcat([-85.5625; -97.6875], [36.625; 48.0625]);
51 | % extent = horzcat([65; 85], [23; 38]);
52 |
53 | % Subset domain
54 | global_domain = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1_5/Image/VICGlobal_domain.nc';
55 | outname_domain = '/Volumes/HD4/SWOTDA/Data/Tuolumne/v1_7/Image_VG/tuo_domain.nc';
56 | subset_domain(extent, global_domain, outname_domain)
57 |
58 | % Subset parameters
59 | global_params = '/Volumes/HD3/VICParametersGlobal/VICGlobal/v1_5/Image/VICGlobal_params.nc';
60 | % outname_params = '/Volumes/HD4/SWOTDA/Data/Tuolumne/v1_4/Image_VICGlobal/params_subL.nc';
61 | outname_params = '/Volumes/HD4/SWOTDA/Data/Tuolumne/v1_7/Image_VG/tuo_params.nc';
62 | subset_parameter(extent, global_params, outname_params)
63 |
64 |
65 |
66 | % takes a long time to run (took a couple hours for the Tuolumne basin test case)
67 | % also uses a lot of RAM, like 20 GB
68 |
--------------------------------------------------------------------------------
/vicmatlab/subsetting/upper_tuolumne_basin_merc.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/vicmatlab/subsetting/upper_tuolumne_basin_merc.tif
--------------------------------------------------------------------------------
/vicmatlab/subsetting/upper_tuolumne_basin_wgs.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/vicmatlab/subsetting/upper_tuolumne_basin_wgs.tif
--------------------------------------------------------------------------------
/vicmatlab/subsetting/write_soils.m:
--------------------------------------------------------------------------------
1 | % Write soils
2 | %
3 | % Writes out the soil parameter file
4 | %
5 | % INPUTS
6 | % precision = number of decimal points for the coordinates/forcing file
7 | % names
8 | % soils = data for soil parameter file
9 | % outname
10 | % outformat = livneh, 2l, or 3l
11 |
12 | function write_soils(precision, soils, outname, outformat)
13 |
14 | % Write out
15 | fstring = ['%.' num2str(precision) 'f'];
16 |
17 | if strcmp(outformat, 'livneh')
18 | % For the Livneh soil parameter file
19 | fspec = ['%d %d ' fstring ' ' fstring ' %.4f %.4f %.4f %.4f %d %.3f %.3f %.3f %.3f %.3f %.3f %d %d %d %.3f %.3f %.3f %.2f %.2f %.2f %.2f %d %d %.3f %.3f %.3f %.3f %.3f %.3f %.2f %.2f %.2f %.2f %.2f %.2f %d %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %d %d %d %d %d\n'];
20 | elseif strcmp(outformat, '2l')
21 | % For the 2-layer soil parameter file from HWSD
22 | fspec = ['%d %d ' fstring ' ' fstring ' ' '%.4f %.4f %.4f %.4f %d %.3f %.3f %.3f %.3f %d %d %.3f %.3f %.2f %.2f %.2f %d %d %.3f %.3f %.3f %.3f %.2f %.2f %.2f %.2f %d %.2f %.2f %.2f %.2f %.2f %.2f %d %d %d %d\n'];
23 | elseif strcmp(outformat, '3l')
24 | % This is used VIC-3L w no optional variables (54 columns in the soil parameter file).
25 | fspec = ['%d %d ' fstring ' ' fstring ' ' '%.4f %.4f %.4f %.4f %d %.3f %.3f %.3f %.3f %.3f %.3f %d %d %d %.3f %.3f %.3f %.2f %.2f %.2f %.2f %.2f %d %.3f %.3f %.3f %.3f %.3f %.3f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.4f %.4f %.2f %d %d %d %d %.2f\n'];
26 | else
27 | error('Please specify a valid value of outformat')
28 | end
29 |
30 | fID = fopen(outname, 'w');
31 | fprintf(fID, fspec, soils');
32 | fclose(fID);
33 | display(['Soils data saved to ' outname])
34 |
35 |
36 | return
--------------------------------------------------------------------------------
/vicmatlab/subsetting/xyz2grid.m:
--------------------------------------------------------------------------------
1 | % Note: I have modified one line of this code (flipping the output
2 | % upside-down) -JRS
3 | %
4 | %
5 |
6 | function varargout = xyz2grid(varargin)
7 | % xyz2grid converts regularly-spaced columnated x,y,z data into gridded data.
8 | %
9 | %% Syntax
10 | %
11 | % Z = xyz2grid(x,y,z)
12 | % Z = xyz2grid(filename)
13 | % Z = xyz2grid(filename,Name,Value)
14 | % [X,Y,Z] = xyz2grid(...)
15 | %
16 | %% Description
17 | %
18 | % Z = xyz2grid(x,y,z) assumes x and y have some form of regularity and puts
19 | % the corresponding values of z into a regular 2D MxN gridded matrix Z.
20 | %
21 | % Z = xyz2grid(filename) loads data from a .xyz file of three columns
22 | % (x, y, and z) then puts the data into a grid. This function assumes the
23 | % input x,y,z data have some gridded regularity, but may have some missing
24 | % data points.
25 | %
26 | % Z = xyz2grid(filename,Name,Value) opens a .xyz file with any textscan
27 | % options Name,Value, for example, 'headerlines',1.
28 | %
29 | % [X,Y,Z] = xyz2grid(...) returns 2D meshgridded X and Y matrices corresponding
30 | % to the values in Z.
31 | %
32 | %% Example
33 | % You may have some columns of x,y, and z values that look like this:
34 | %
35 | % x = [1 1 2 2 2 3 3];
36 | % y = [1 2 1 2 3 1 3];
37 | % z = [1 2 4 5 6 7 9];
38 | %
39 | % scatter(x,y,500,z,'filled')
40 | % axis([0 4 0 4])
41 | % colorbar
42 | %
43 | % From the scatter plot above, you can see that there is some gridded
44 | % regularity to the data, even though a couple of spots in the grid
45 | % are missing. That's okay. Let's grid it up:
46 | %
47 | % [X,Y,Z] = xyz2grid(x,y,z)
48 | % X =
49 | % 1 2 3
50 | % 1 2 3
51 | % 1 2 3
52 | % Y =
53 | % 3 3 3
54 | % 2 2 2
55 | % 1 1 1
56 | % Z =
57 | % NaN 6 9
58 | % 2 5 NaN
59 | % 1 4 7
60 | %
61 | %% Author Info
62 | % This script was written by Chad A. Greene of the University of Texas
63 | % at Austin's Institute for Geophysics (UTIG), April 2016.
64 | % http://www.chadagreene.com
65 | %
66 | % See also xyzread and accumarray.
67 |
68 | %% Error checks and input parsing:
69 |
70 | narginchk(1,inf)
71 |
72 | % Has the user input x,y,z coordinates or a .xyz filename? Assume filename if first input is a string:
73 | if isnumeric(varargin{1})
74 | x = varargin{1};
75 | y = varargin{2};
76 | z = varargin{3};
77 | else
78 | [x,y,z] = xyzread(varargin{:});
79 | end
80 |
81 | assert(isequal(size(x),size(y),size(z))==1,'Dimensions of x,y, and z must match.')
82 | assert(isvector(x)==1,'Inputs x,y, and z must be vectors.')
83 |
84 | %% Grid xyz:
85 |
86 | % Get unique values of x and y:
87 | [xs,~,xi] = unique(x(:),'sorted');
88 | [ys,~,yi] = unique(y(:),'sorted');
89 |
90 | % Before we go any further, we better make sure we're not gridding scattered data.
91 | % This is not a perfect assessor, but it's at least some kind of check:
92 | if numel(xs)==numel(z)
93 | warning 'It does not seem like the xyz dataset is gridded. You may be attempting to grid scattered data, but I will try to put it into a 2D matrix anyway. Check the output spacing of X and Y.';
94 | end
95 |
96 | % Sum up all the Z values that in each x,y grid point:
97 | Z = accumarray([yi xi],z(:),[],[],NaN);
98 |
99 | % ------------------------------------------------------------------------
100 | % ------------------------------------------------------------------------
101 | % ------------------------------------------------------------------------
102 | % Flip Z to match X,Y and to be correctly oriented in ij image coordinates:
103 | % Z = flipud(Z); % commented out 8/8/2019 JRS
104 | % ------------------------------------------------------------------------
105 | % ------------------------------------------------------------------------
106 | % ------------------------------------------------------------------------
107 |
108 | %% Package up the outputs:
109 |
110 | switch nargout
111 | case 1
112 | varargout{1} = Z;
113 |
114 | case 3
115 |
116 | % Create a meshgrid of x and y:
117 | [varargout{1},varargout{2}] = meshgrid(xs,flipud(ys));
118 | varargout{3} = Z;
119 |
120 | otherwise
121 | error('Wrong number of outputs.')
122 | end
123 |
124 |
125 | end
--------------------------------------------------------------------------------
/vicmatlab/utility/GetCoords.m:
--------------------------------------------------------------------------------
1 | function [lat, lon] = GetCoords(gridcells, precision, prefix)
2 |
3 | % Extracts coordinates (numeric) from flux output file names.
4 | % Assumes northwestern hemisphere (positive latitudes, negative longitudes)
5 | %
6 | % INPUTS
7 | % gridcells = locations of the gridcells (lat/lon). Output from LoadVICResults.
8 | % precision = number of decimal points of precision for the VIC flux output file names
9 | %
10 | % OUTPUTS
11 | % Coordinates of grid cell centroids, as a numeric array
12 |
13 | ncells = length(gridcells);
14 |
15 | % Extract numbers from within the strings in the cell array using regexp
16 |
17 | %% Make an array of signs
18 |
19 | % Here, we use the signstr values in combination with underscore locations to
20 | % determine whether lat, lon, or both should be negative.
21 |
22 | % This will break if there are '-' in the file name, aside from the
23 | % negative signs
24 |
25 | % This is sensitive to the number of underscores in the prefix. If there
26 | % are underscores in the prefix, they need to be account for appropriately.
27 |
28 | n_underscores_in_prefix = length(strfind(prefix, '_'));
29 |
30 | underscore_locations = strfind(gridcells, '_');
31 | signstr = strfind(gridcells, '-');
32 |
33 | lon_signs = ones(ncells, 1);
34 | lat_signs = ones(ncells, 1);
35 |
36 | for k=1:ncells
37 |
38 | switch length(signstr{k})
39 | case 0
40 | % disp('Both lat and lon are positive')
41 | 1;
42 | case 1
43 | % disp('Either lat or lon is negative')
44 | % if signstr{k} == underscore_locations{k}(1) + 1
45 | % if signstr{k} == underscore_locations{k}(2) + 1
46 | if signstr{k} == underscore_locations{k}(n_underscores_in_prefix) + 1
47 | lat_signs(k) = -1;
48 | % elseif signstr{k} == underscore_locations{k}(3) + 1
49 | elseif signstr{k} == underscore_locations{k}(n_underscores_in_prefix + 2) + 1
50 | % elseif signstr{k} == underscore_locations{k}(4) + 1
51 | lon_signs(k) = -1;
52 | end
53 | case 2
54 | % disp('Both lat and lon are negative')
55 | lon_signs(k) = -1;
56 | lat_signs(k) = -1;
57 | end
58 |
59 | end
60 |
61 |
62 |
63 | %% Assemble coordinates into lat/lon vectors
64 |
65 | % Get coordinates (sans sign) from the input file names
66 | gridcells_numbers = regexprep(gridcells,'\D',''); % this replaces non-numeric digits with "".
67 |
68 | % There is probably a way to implement this without a loop
69 | % Also, the switch-case could definitely be rewritten/removed
70 | lon = NaN(ncells,1);
71 | lat = NaN(ncells,1);
72 | for k = 1:ncells
73 |
74 | ndigits = size(gridcells_numbers{1},2);
75 | str1 = gridcells_numbers{k}(1:2);
76 | str2 = gridcells_numbers{k}(3:2 + precision);
77 | switch ndigits
78 | case 12 % 2 digits for lat and 2 for lon (precision = 4)
79 | str3 = gridcells_numbers{k}(3 + precision:4 + precision);
80 | str4 = gridcells_numbers{k}(2*precision:end);
81 | case 13 % 2 digits for lat and 3 for lon (precision = 4)
82 | str3 = gridcells_numbers{k}(3 + precision:2*precision + 1);
83 | str4 = gridcells_numbers{k}(2*precision + 2:end);
84 | case 14 % 2 digits for lat and 2 for lon (precision = 5)
85 | str3 = gridcells_numbers{k}(3 + precision:2*precision - 1);
86 | str4 = gridcells_numbers{k}(2*precision:end);
87 | case 15 % 2 digits for lat and 3 for lon (precision = 5)
88 | str3 = gridcells_numbers{k}(3 + precision:2*precision);
89 | str4 = gridcells_numbers{k}(1 + 2*precision:end);
90 | otherwise
91 | error('Incorrect number of characters in gridcells string. Precision must be 4 or 5 digits.');
92 | end
93 |
94 | lat(k) = str2double([str1 '.' str2]);
95 |
96 | lon(k) = str2double([str3 '.' str4]);
97 |
98 | end
99 |
100 | % Append the signs
101 | lon = lon.*lon_signs;
102 | lat = lat.*lat_signs;
103 |
104 | % Indexing convention
105 | % i, x
106 | % j, y
107 | % k, ncells
108 |
109 |
110 | end
--------------------------------------------------------------------------------
/vicmatlab/utility/basin_mask2coordinate_list.m:
--------------------------------------------------------------------------------
1 | % Obtains a list of coordinates from a basin mask
2 | %
3 | % The coordinates are all the points where the basin mask is not NaN.
4 | %
5 | % Example
6 | % maskname = '/Volumes/HD4/SWOTDA/Data/Colorado/colo_mask.tif';
7 | % coords = basin_mask2coordinate_list(maskname)
8 |
9 | function extent1 = basin_mask2coordinate_list(maskname)
10 |
11 | [basin_mask, R] = geotiffread2(maskname);
12 |
13 | basin_mask = double(basin_mask);
14 | basin_mask(basin_mask~=1) = NaN;
15 |
16 | ncells = length(basin_mask(~isnan(basin_mask)));
17 | [nx, ny] = size(basin_mask);
18 |
19 | k = 1;
20 | lon1 = zeros(ncells, 1);
21 | lat1 = zeros(ncells, 1);
22 | disp(['nx = ' num2str(nx)])
23 | for i=1:nx
24 | for j=1:ny
25 | if ~isnan(basin_mask(i,j))
26 | [lat1(k), lon1(k)] = pix2latlon(R, i, j);
27 | k = k + 1;
28 | end
29 | end
30 | if mod(i,100)==0
31 | disp(i)
32 | end
33 | end
34 |
35 | extent1 = [lon1, lat1];
36 |
37 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/calc_water_year_average.m:
--------------------------------------------------------------------------------
1 | % Calculate water year average
2 | %
3 | % Calculate the average value of a time series variable on each day of the
4 | % water year. Drops the last day of a leap year.
5 |
6 | function [var_avg, dowy] = calc_water_year_average(t, var)
7 |
8 | [t, var] = check_water_year(t, var);
9 |
10 | dowy = 1:365;
11 |
12 | % Choosing an arbitrary year with 365 days
13 | dowy = datetime(2000, 10 ,1):datetime(2001,9,30);
14 |
15 | var_avg = NaN(365,1);
16 | for i=1:365
17 | ind = month(t) == month(dowy(i)) & day(t) == day(dowy(i));
18 | var_avg(i) = mean(var(ind));
19 | end
20 |
21 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/cfs2cms.m:
--------------------------------------------------------------------------------
1 | % cfs to cms
2 | %
3 | % INPUTS
4 | % Qcfs = volumetric flowrate, English units
5 | %
6 | % OUTPUTS
7 | % Qcms = volumetric flowrate, metric units
8 |
9 | function Qcms = cfs2cms(Qcfs)
10 |
11 | Qcms = Qcfs*(12/39.37)^3;
12 |
13 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/classic_outputs2image.m:
--------------------------------------------------------------------------------
1 | % Classic (output) to Image
2 | %
3 | % Converts VIC classic mode outputs to image mode NetCDF format
4 | % 8/18/2020 JRS
5 | %
6 | % INPUTS
7 | % classic_outdir: location where classic mode VIC outputs are located
8 | % image_outdir: save location for converted output file
9 | % prefix: must include the underscore, if there is one. Example: "fluxes_"
10 | % varnames: can specify variable names to convert, or leave blank to
11 | % convert all variables
12 | %
13 | % Subsetting times has not been fully implemented yet.
14 |
15 | function ncoutname = classic_outputs2image(classic_outdir, prefix, image_outdir, varargin)
16 |
17 | %% Initialization
18 |
19 | numvarargs = length(varargin);
20 | if numvarargs > 3
21 | error('The max number of optional arguments is 3')
22 | end
23 |
24 | % Option to convert all or just some of the outputs
25 | optargs = {'all', NaN, NaN};
26 | optargs(1:numvarargs) = varargin;
27 | [varnames, start_date, end_date] = optargs{:};
28 |
29 | if ~exist(image_outdir, 'dir')
30 | mkdir(image_outdir)
31 | end
32 |
33 | classic_names = dir(fullfile(classic_outdir, [prefix '*.txt']));
34 | dat = dlmread(fullfile(classic_outdir, classic_names(1).name), '\t', 3, 0);
35 | t = datetime(dat(:,1), dat(:,2), dat(:,3));
36 |
37 | if isnan(start_date)
38 | start_date = t(1);
39 | end_date = t(end);
40 | else
41 | [~, i1] = ismember(t, start_date);
42 | [~, i2] = ismember(t, end_date);
43 | t = start_date:end_date;
44 | end
45 |
46 | if strcmp(varnames, 'all')
47 | varnames = get_vic_header(fullfile(classic_outdir, classic_names(1).name), 3);
48 | end
49 |
50 | ncoutname = fullfile(image_outdir, ...
51 | [prefix, num2str(year(start_date),'%02.f'), '-', num2str(month(start_date),'%02.f'), '-' num2str(day(start_date),'%02.f'), '.nc']);
52 |
53 | %% Lon, lat, time, mask
54 |
55 | [lon, lat] = get_coordinates_from_VIC_file(classic_outdir, prefix);
56 | mask = xyz2grid(lon, lat, ones(length(lon), 1));
57 | resolution = mode(abs(diff(lon)));
58 |
59 | % if there is an issue with the grid, it's probably bc of this line.
60 | % Could change grid cell center vs. corner definition.
61 | R = makerefmat(min(lon), min(lat), resolution, resolution);
62 |
63 | [lon1, lat1] = pixcenters(R, size(mask));
64 |
65 | mask(isnan(mask)) = 0;
66 | mask = single(mask);
67 |
68 | nccreate(ncoutname,'lon',...
69 | 'Datatype','double',...
70 | 'Dimensions',{'lon',length(lon1)},...
71 | 'Format','classic')
72 |
73 | nccreate(ncoutname,'lat',...
74 | 'Datatype','double',...
75 | 'Dimensions',{'lat',length(lat1)},...
76 | 'Format','classic')
77 |
78 | nccreate(ncoutname,'time',...
79 | 'Datatype','int32',...
80 | 'Dimensions',{'time',length(t)},...
81 | 'Format','classic')
82 |
83 | nccreate(ncoutname,'mask',...
84 | 'Datatype','single',...
85 | 'Dimensions',{'lon',length(lon1),'lat',length(lat1)},...
86 | 'Format','classic')
87 |
88 | tt = (0:length(t)-1)'; % units are days since start_date
89 | ncwrite(ncoutname,'time',tt);
90 | ncwrite(ncoutname,'lon',lon1);
91 | ncwrite(ncoutname,'lat',lat1);
92 | ncwrite(ncoutname,'mask',mask');
93 |
94 | ncwriteatt(ncoutname,...
95 | 'time','calendar','proleptic_gregorian');
96 | ncwriteatt(ncoutname,...
97 | 'time','units',['days since ', num2str(year(start_date),'%02.f'), '-', num2str(month(start_date),'%02.f'), '-', num2str(day(start_date),'%02.f')]);
98 |
99 | ncwriteatt(ncoutname,...
100 | 'lon','standard_name','longitude');
101 | ncwriteatt(ncoutname,...
102 | 'lon','long_name','longitude of grid cell center');
103 | ncwriteatt(ncoutname,...
104 | 'lon','units','degrees_east');
105 | ncwriteatt(ncoutname,...
106 | 'lon','axis','X');
107 |
108 | ncwriteatt(ncoutname,...
109 | 'lat','standard_name','latitude');
110 | ncwriteatt(ncoutname,...
111 | 'lat','long_name','latitude of grid cell center');
112 | ncwriteatt(ncoutname,...
113 | 'lat','units','degrees_north');
114 | ncwriteatt(ncoutname,...
115 | 'lat','axis','Y');
116 |
117 | ncwriteatt(ncoutname,...
118 | 'mask','comment','NaN indicates cell is not active');
119 | ncwriteatt(ncoutname,...
120 | 'mask','long_name','fraction of grid cell that is activedomain mask');
121 | ncwriteatt(ncoutname,...
122 | 'mask','note','unitless');
123 |
124 | %% Flux variables
125 |
126 | nt = length(t);
127 | nx = length(unique(lon));
128 | ny = length(unique(lat));
129 | for k=4:length(varnames)
130 |
131 | % Read in flux variable from classic mode outputs
132 | var = parload(classic_outdir, prefix, 0, k);
133 |
134 | % Make into a (masked) map to save
135 | output_map = NaN(ny, nx, nt); % this is the correct orientation
136 | for tt=1:nt
137 | output_map(:,:,tt) = xyz2grid(lon, lat, var(tt,:)');
138 | end
139 |
140 | % Removing the "OUT_" part of the name
141 | temp = strsplit(varnames{k}, '_');
142 |
143 | if length(temp) == 2
144 | varnames{k} = lower(temp{2});
145 | elseif length(temp) == 3
146 | varnames{k} = lower([temp{2} '_' temp{3}]);
147 | else
148 | varnames{k} = lower([temp{2} '_' temp{3}, '_', temp{4}]);
149 | end
150 |
151 | nccreate(ncoutname,varnames{k},...
152 | 'Datatype','double',...
153 | 'Dimensions',{'lon',length(lon1),'lat',length(lat1),'time',nt}, ...
154 | 'Format','classic')
155 |
156 | ncwrite(ncoutname, varnames{k}, permute(output_map, [2,1,3]));
157 |
158 | end
159 |
160 | return
161 |
162 |
163 |
164 |
--------------------------------------------------------------------------------
/vicmatlab/utility/crop_time_series.m:
--------------------------------------------------------------------------------
1 | % Crop time series
2 | %
3 | % Crops two times series to match
4 | % Buggy: [y1,y2,t] = crop_time_series(netrad(site_num,:)', totalnet_all, time_vic, tthr_all);
5 |
6 | function [y1,y2,t] = crop_time_series(y1, y2, t1, t2)
7 |
8 | if t1(1) < t2(1) & t1(end) < t2(end)
9 | i1 = find(t1 == t2(1));
10 | i2 = find(t2 == t1(end));
11 | t = t1(i1:end);
12 | y1 = y1(i1:end);
13 | y2 = y2(1:i2);
14 |
15 | elseif t1(1) > t2(1) & t1(end) > t2(end)
16 | i1 = find(t2 == t1(1));
17 | i2 = find(t1 == t2(end));
18 | t = t1(1:i2);
19 | y1 = y1(1:i2);
20 | y2 = y2(i1:end);
21 |
22 | elseif t1(end) < t2(1)
23 | error('Time series do not overlap')
24 |
25 | elseif t1(1) < t2(1) & t1(end) > t2(end)
26 | % t2 is contained within t1
27 | t = t2;
28 | i1 = find(t1 == t2(1));
29 | i2 = find(t1 == t2(end));
30 | y1 = y1(i1:i2);
31 |
32 | elseif t1(1) > t2(1) & t1(end) < t2(end)
33 | % t1 is contained within t2
34 | t = t1;
35 | i1 = find(t2 == t1(1));
36 | i2 = find(t2 == t1(end));
37 | y2 = y2(i1:i2);
38 |
39 | end
40 |
41 |
42 | firsttime = max(t1(1), t2(1));
43 | lasttime = min(t1(end), t2(end));
44 |
45 |
46 |
47 |
48 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/crop_ts.m:
--------------------------------------------------------------------------------
1 | % Crop time series
2 | %
3 | % INPUTS
4 | % y = variable
5 | % t = datetime vector
6 | % d1, d2 = initial and final datetimes
7 |
8 | function [y2, t2] = crop_ts(y, t, d1, d2)
9 |
10 | i1 = find(t == d1);
11 | i2 = find(t == d2);
12 | y2 = y(i1:i2);
13 | t2 = t(i1:i2);
14 |
15 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/daily_to_monthly.m:
--------------------------------------------------------------------------------
1 | % Utility function for aggregating daily to monthly data
2 | %
3 | % t1 must be a column vector (nt by 1)
4 |
5 | function [t_m, q_m] = daily_to_monthly(t1, q1, method)
6 |
7 | YM = unique([year(t1), month(t1)], 'rows');
8 | nt_m = size(YM, 1);
9 | q_m = zeros(nt_m, 1);
10 | t_m = datetime(YM(:,1), YM(:,2), 15);
11 |
12 | for t=1:nt_m
13 | ind = year(t1) == YM(t,1) & month(t1) == YM(t,2);
14 | if strcmp(method, 'mean')
15 | q_m(t) = mean(q1(ind));
16 | elseif strcmp(method, 'sum')
17 | q_m(t) = sum(q1(ind));
18 | end
19 | end
20 |
21 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/find_closest.m:
--------------------------------------------------------------------------------
1 | % Find closest
2 | %
3 | % Given a coordinate (x,y), finds the closest coordinate to (x,y) in a list
4 | % of coordinates, given a search range
5 | %
6 |
7 | function [sind, mindist] = find_closest(coord, coordlist, search_range)
8 |
9 | lon1 = coord(1);
10 | lat1 = coord(2);
11 |
12 | lon = coordlist(:,1);
13 | lat = coordlist(:,2);
14 |
15 | sind = find((abs(lon - lon1) <= search_range/2) & (abs(lat - lat1) <= search_range/2));
16 | switch length(sind)
17 | case 0
18 | error('no nearby points found. use a larger search radius')
19 | case 1
20 | disp('one nearby point found')
21 | mindist = sqrt((lon(sind) - lon1).^2 + (lat(sind) - lat1).^2);
22 | otherwise
23 | disp('multiple nearby points found')
24 | distances = sqrt((lon(sind) - lon1).^2 + (lat(sind) - lat1).^2);
25 | [mindist, minind] = min(distances);
26 | sind = sind(minind); % keep the closest station
27 | end
28 |
29 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/find_line.m:
--------------------------------------------------------------------------------
1 | % Find line
2 | %
3 | % July 17, 2020
4 | % Finds the line in a text file containing the phrase (findstring)
5 | % Note: only finds the first instance
6 |
7 | function i = find_line(fname, findstring)
8 |
9 | A = read_global_param_file(fname);
10 |
11 | nrows = length(A);
12 | for i=1:(nrows-1) % avoids issues with last line
13 | temp = strsplit(A{i}, findstring);
14 | if length(temp) > 1
15 | break
16 | end
17 | end
18 |
19 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/get_coordinates_from_VIC_file.m:
--------------------------------------------------------------------------------
1 | % Get coordinates from VIC file
2 | %
3 | % INPUTS
4 | % folder = name of directory where VIC files are stored
5 | % option = file prefix ('Forcing' or 'Flux', for example)
6 | %
7 | % OUTPUTS
8 | % lat lon coordinates for each VIC file
9 |
10 | function [lon, lat] = get_coordinates_from_VIC_file(folder, prefix)
11 |
12 | fnames = dir(fullfile(folder, [prefix '*']));
13 | ncells = length(fnames);
14 | lat = zeros(ncells,1);
15 | lon = zeros(ncells,1);
16 |
17 | n_underscores = length(strfind(prefix, '_'));
18 |
19 | for k=1:ncells
20 |
21 | % one or the other code block is used, depending on the format of the
22 | % filenames
23 | if n_underscores == 1
24 | tmp = strsplit(fnames(k).name, '_');
25 | lat(k) = str2double(tmp{2});
26 | tmp = strsplit(tmp{3}, '.txt');
27 | lon(k) = str2double(tmp{1});
28 | elseif n_underscores == 2
29 | tmp = strsplit(fnames(k).name, '_');
30 | lat(k) = str2double(tmp{3});
31 | tmp = strsplit(tmp{4}, '.txt');
32 | lon(k) = str2double(tmp{1});
33 | end
34 | end
35 |
36 | return
37 |
--------------------------------------------------------------------------------
/vicmatlab/utility/get_vic_header.m:
--------------------------------------------------------------------------------
1 | % Gets the header from a VIC 5 classic output file
2 |
3 | function header_names = get_vic_header(fname, lineno)
4 |
5 | eb_ID = fopen(fname);
6 | for i=1:lineno % cycles through to the third line
7 | eb_header = fgetl(eb_ID);
8 | end
9 | header_names = strsplit(eb_header);
10 |
11 | end
--------------------------------------------------------------------------------
/vicmatlab/utility/getlatlon.m:
--------------------------------------------------------------------------------
1 | % Get coordinates (lat/lon vectors) from R and dem
2 | function [ulon, ulat] = getlatlon(A, R)
3 |
4 | [nx, ny] = size(A);
5 |
6 |
7 | x=(1:nx)';
8 | y=ones(length(x),1);
9 |
10 | xx = repmat(x, ny, 1);
11 |
12 | % For this bit of code, credit to:
13 | % https://www.mathworks.com/matlabcentral/answers/16270-create-vector-of-repeating-elements-sort-of
14 | v=repmat(1:ny, [nx 1]);
15 | yy = v(:);
16 |
17 | [lat, lon] = intrinsicToGeographic(R,xx,yy);
18 |
19 | ulat = unique(lat);
20 | ulon = unique(lon);
21 |
22 | end
--------------------------------------------------------------------------------
/vicmatlab/utility/hourly_to_daily.m:
--------------------------------------------------------------------------------
1 | % Utility function for aggregating hourly to daily data
2 | %
3 | % t1 must be a column vector (nt by 1)
4 |
5 | function [t_m, q_m] = hourly_to_daily(t1, q1, method)
6 |
7 | if nargin < 3
8 | error('Need additional argument')
9 | end
10 |
11 | if size(t1,2)>size(t1,1)
12 | t1 = t1';
13 | end
14 |
15 | ncols = size(q1,2);
16 |
17 | YMD = unique([year(t1), month(t1), day(t1)], 'rows');
18 | nt_m = size(YMD, 1);
19 | q_m = zeros(nt_m, ncols);
20 | t_m = datetime(YMD(:,1), YMD(:,2), YMD(:,3));
21 |
22 | for t=1:nt_m
23 | ind = year(t1) == YMD(t,1) & month(t1) == YMD(t,2) & day(t1) == YMD(t,3);
24 | try
25 | if strcmp(method, 'mean')
26 | q_m(t,:) = mean(q1(ind,:));
27 | elseif strcmp(method, 'sum')
28 | q_m(t,:) = sum(q1(ind,:));
29 | end
30 | catch
31 | continue;
32 | end
33 | end
34 |
35 | % figure
36 | % plot(t, q_m)
37 |
38 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/latlon_from_raster.m:
--------------------------------------------------------------------------------
1 | % Lat lon from raster
2 | %
3 | % Get list of latlon coordinates from raster
4 | % 5/23/2020 JRS
5 |
6 | function [lon, lat] = latlon_from_raster(raster, R)
7 |
8 | ncells = length(raster(~isnan(raster)));
9 | [nx, ny] = size(raster);
10 |
11 | k = 1;
12 | lon = zeros(ncells, 1);
13 | lat = zeros(ncells, 1);
14 | for i=1:nx
15 | for j=1:ny
16 | if ~isnan(raster(i,j))
17 | [lat(k), lon(k)] = pix2latlon(R, i, j);
18 | k = k + 1;
19 | end
20 | end
21 | end
22 |
23 | end
24 | % Rmat = georefobj2mat(R, 'LL');
25 | % geotiffread2
--------------------------------------------------------------------------------
/vicmatlab/utility/load_streamflow_data.m:
--------------------------------------------------------------------------------
1 | % Load streamflow data
2 | %
3 | % Loads streamflow data from a text file with YMDQ fields
4 |
5 | function [t, q] = load_streamflow_data(filename, q_col, format)
6 |
7 | % filename = '/home/jschap/Documents/ESSD/data/naturalized_flow_usgs_09380000.txt'
8 |
9 | dat = readmatrix(filename, 'TreatAsMissing',{'NA'}, 'Delimiter', ' ');
10 | if size(dat,2) > 10
11 | dat = load(filename);
12 | end
13 |
14 | if size(dat,2) < 4
15 | dat = readmatrix(filename, 'TreatAsMissing',{'NA'}, 'Delimiter', '\t');
16 | end
17 |
18 | if strcmp(format, 'daily')
19 | t = datetime(dat(:,1), dat(:,2), dat(:,3));
20 | elseif strcmp(format, 'monthly')
21 | t = datetime(dat(:,1), dat(:,2), 15);
22 | end
23 |
24 | q = dat(:,q_col);
25 |
26 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/match_coords.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jschap1/VICMATLAB/a5659c8cfde27531dbf9ccbe477aadec01fa3385/vicmatlab/utility/match_coords.m
--------------------------------------------------------------------------------
/vicmatlab/utility/match_time_series.m:
--------------------------------------------------------------------------------
1 | % Match time series
2 | %
3 | % This function takes two or more time series with different start/end
4 | % dates as inputs, and outputs clipped time series with matching start/end dates.
5 | %
6 | % INPUTS
7 | % ts_struct = structure containing time series (t1, y1), (t2, y2), etc.
8 | % names must be as follows:
9 | % ts_struct.t.t1, .t2, .t3
10 | % ts_struct.y.y1, .y2, .y3
11 | %
12 | % OUTPUTS
13 | % t_out = datetime vector
14 | % y_out = matrix containing the time series variables
15 | %
16 | % WORK IN PROGRESS..
17 |
18 | function [t_out, y_out] = match_time_series(start_date, end_date, t, y)
19 |
20 | % nseries = length(varargin);
21 |
22 | [~, i1] = ismember(start_date, t);
23 | [~, i2] = ismember(end_date, t);
24 |
25 | t_out = t(i1:i2);
26 | y_out = y(i1:i2);
27 |
28 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/mmday2cms.m:
--------------------------------------------------------------------------------
1 | % mm/day to m^3/s
2 | %
3 | % Converts VIC outputs (e.g. runoff and baseflow) to volumetric flowrate
4 | %
5 | % INPUTS
6 | % Q = runoff depth (basin or pixel), in mm/day
7 | % A = grid cell area, in km^2
8 | %
9 | % OUTPUTS
10 | % Qv = volumetric flowrate
11 |
12 | function Qv = mmday2cms(Q, A_cell)
13 |
14 | cf = 1000*A_cell/(24*3600);
15 | Qv = cf*Q;
16 |
17 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/padfill.m:
--------------------------------------------------------------------------------
1 | % PadFill
2 | %
3 | % Fills missing data in time series (t2, y2).
4 | % t1 must include t2 (currently)
5 |
6 | function yprime = padfill(t1, t2, y2, fillval)
7 |
8 | if t1(1) < t2(1) && t1(end) > t2(end)
9 | yprime = fillval*ones(length(t1), 1);
10 | [a,b] = ismember(t2, t1);
11 | [c,d] = ismember(t1, t2);
12 | yprime(c) = y2;
13 | else
14 | error('t1 does not include t2')
15 | end
16 |
17 | % figure
18 | % plot(t1, yprime)
19 |
20 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/read_usgs.m:
--------------------------------------------------------------------------------
1 | % Function for reading streamflow data from USGS
2 | %
3 | %
4 | function [t_usgs, q_usgs] = read_usgs(fname, start_date, end_date, varargin)
5 |
6 | % Set default values for optional arguments
7 |
8 | numvarargs = length(varargin);
9 | if numvarargs > 3
10 | error('subset_forcings requires at most one optional input');
11 | end
12 | optargs = {0};
13 | optargs(1:numvarargs) = varargin;
14 | [plotflag] = optargs{:};
15 |
16 | %% Process data
17 |
18 | dat = readmatrix(fname);
19 | usgs = struct();
20 | usgs.t = datetime(dat(:,1), dat(:,2), 15);
21 | usgs.Q_cms = dat(:,4);
22 |
23 | % USGS
24 | i1 = find(usgs.t == start_date);
25 | i2 = find(usgs.t == end_date);
26 | t_usgs = usgs.t(i1:i2);
27 | q_usgs = usgs.Q_cms(i1:i2);
28 |
29 | if plotflag
30 | figure, plot(t_usgs, q_usgs)
31 | end
32 |
33 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/remove_empty_rowcol.m:
--------------------------------------------------------------------------------
1 | % Removes empty (all NaN) rows or columns from a matrix
2 | %
3 | % 8/10/2020 JRS
4 |
5 | function B = remove_empty_rowcol(A)
6 |
7 | % empty_cols = find(nansum(A,1)==0);
8 | % empty_rows = (nansum(A,2)==0);
9 |
10 | non_empty_cols = find(nansum(A,1)~=0);
11 | non_empty_rows = (nansum(A,2)~=0);
12 |
13 | B = A(non_empty_rows, :);
14 | B = B(:,non_empty_cols);
15 |
16 | return
--------------------------------------------------------------------------------
/vicmatlab/utility/rescale_mean.m:
--------------------------------------------------------------------------------
1 | % Rescales Y to match the mean of X
2 | %
3 | % Keeps the spatial pattern of Y
4 |
5 | function Yprime = rescale_mean(X, Y, varargin)
6 |
7 | if nargin > 3
8 | error('maximum number of parameters is 3')
9 | end
10 |
11 | optargs = {1};
12 | optargs(1) = varargin;
13 | [negative_allowed] = optargs{:};
14 |
15 | if negative_allowed
16 | b = mean(Y) - mean(X);
17 | Yprime = Y - b;
18 | else
19 | t = min(Y) + 1e-3;
20 | s = (mean(X) - t)/mean(Y);
21 | Yprime = s*Y + t;
22 | end
23 |
24 | return
25 |
--------------------------------------------------------------------------------
/vicmatlab/utility/upscale_raster.m:
--------------------------------------------------------------------------------
1 | % Upscale raster
2 | %
3 | %
4 | % INPUTS
5 | % r = input raster
6 | % lons = list of input longitudes
7 | % lats = list of input latitudes
8 | % newres, oldres = new and old resolutions
9 | % method = linear, nearest, etc.
10 |
11 | function [newr, newlons, newlats] = upscale_raster(r, lons, lats, newres, oldres, method)
12 |
13 | remove_nan = 1; % flag for removing nan values from output
14 |
15 | [m1, n1] = size(r); % original dimensions
16 |
17 | f = newres/oldres; % upscaling (or downscaling) factor
18 |
19 | % Upscale (or downscale) (method from Walter Roberson in MATLAB Answers)
20 | minlat = min(lats);
21 | maxlat = max(lats);
22 | minlon = min(lons);
23 | maxlon = max(lons);
24 |
25 | oldlats = linspace(minlat, maxlat, m1);
26 | oldlons = linspace(minlon, maxlon, n1)';
27 |
28 | % find which method works best and use that
29 |
30 | newlats1 = (minlat - oldres/2):newres:(maxlat + oldres/2); % include outside edge
31 | newlons1 = (minlon - oldres/2):newres:(maxlon + oldres/2);
32 | newlons1 = newlons1';
33 |
34 | newlats2 = (minlat - oldres/2) + newres:newres:(maxlat + oldres/2) - newres; % exclude outside edge
35 | newlons2 = (minlon - oldres/2) + newres:newres:(maxlon + oldres/2) - newres;
36 | newlons2 = newlons2';
37 |
38 | a1 = abs(newlons1(1) - minlon) + abs(newlons1(end) - maxlon);
39 | a2 = abs(newlons2(1) - minlon) + abs(newlons2(end) - maxlon);
40 | ii = find(min([a1,a2]));
41 |
42 | b1 = abs(newlats1(1) - minlat);
43 | b2 = abs(newlats1(end) - maxlat);
44 | jj = find(min([b1,b2]));
45 |
46 | if ii==1
47 | newlons = newlons1;
48 | elseif ii==2
49 | newlons = newlons2;
50 | end
51 |
52 | if jj==1
53 | newlats = newlats1;
54 | elseif jj==2
55 | newlats = newlats2;
56 | end
57 |
58 | newr = interp2(oldlats, oldlons, r', newlats, newlons, method);
59 | newr = newr';
60 |
61 | if remove_nan
62 | newr(isnan(newr))=0;
63 | end
64 |
65 | return
--------------------------------------------------------------------------------