├── .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 |
97 | 98 | 99 |
100 | 101 |
102 | 103 | 104 |
105 | 106 | Built with MkDocs using a theme provided by Read the Docs. 107 |
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 ''; 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 --------------------------------------------------------------------------------