{"id":20074921,"url":"https://github.com/ncss-tech/rosetta-docs","last_synced_at":"2026-01-19T18:31:44.007Z","repository":{"id":69653046,"uuid":"332854975","full_name":"ncss-tech/ROSETTA-docs","owner":"ncss-tech","description":null,"archived":false,"fork":false,"pushed_at":"2021-02-11T15:23:40.000Z","size":843,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-02-12T21:22:54.707Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ncss-tech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-01-25T19:10:54.000Z","updated_at":"2024-02-22T14:30:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"776a34ad-18fe-453f-83be-96dca19950e1","html_url":"https://github.com/ncss-tech/ROSETTA-docs","commit_stats":{"total_commits":38,"total_committers":2,"mean_commits":19.0,"dds":0.07894736842105265,"last_synced_commit":"b88e5e9621140a84477dc9ef9a56bd6f6c3451e0"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncss-tech%2FROSETTA-docs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncss-tech%2FROSETTA-docs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncss-tech%2FROSETTA-docs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncss-tech%2FROSETTA-docs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ncss-tech","download_url":"https://codeload.github.com/ncss-tech/ROSETTA-docs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247500464,"owners_count":20948881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T14:56:08.803Z","updated_at":"2026-01-19T18:31:43.965Z","avatar_url":"https://github.com/ncss-tech.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ROSETTA-docs\n\n![ROSETTA Banner](https://github.com/ncss-tech/ROSETTA-docs/blob/main/static-figures/Rosetta_Banner.png)\n\nRichard Reid, Dylan Beaudette, Maria Hrebik, Kelly Scott, Todd Skaggs\n\n2021-01-12\n\n## Introduction\n\nThe purpose of this site is to document the procedure for taking NRCS soil parameters and estimate soil water characteristics and dynamic conductivity for use in various modeling of water and nutrient transports through the soil. Historically, NRCS has relied on the ROSETTA model to complete this estimation. ROSETTA was developed by ARS through the work of Schaap, et al. Most recently the ROSETTA model has been updated to fit into the web environment by Dr. Todd Skaggs (USDA-ARS) and links to the work of Zhang and Schaap, (2017). This site provides the process, assumptions, and code associated with this transition.  \n\nROSETTA can be used to estimate the van Genuchten hydraulic parameters that include the following:\n\n   * **theta_r:** the residual soil water content, $(cm^{3} / cm^{3})$\n\n   * **theta_s:** the saturated soil water content, $(cm^{3} / cm^{3})$\n\n   * **alpha:**  parameter of the van Genuchten equation corresponding approximately to the inverse of the air-entry value, $(cm^{-1})$\n\n   * **n:** the empirical shape-defining parameters in the van Genuchten equation, (dimensionless) \n\n   * **Ksat** the effective saturated hydraulic conductivity, $(cm / day)$\n\n\nThe ROSETTA model relies on a minimum of 3 soil properties, with increasing (expected) accuracy as additional properties are included:\n\n   * required, sand, silt, clay: USDA soil texture separates (percentages) that sum to 100%\n   * optional, bulk density (any moisture basis): mass per volume after accounting for \u003e2mm fragments, units of gm/cm3\n   * optional, volumetric water content at 33 kPa: roughly “field capacity” for most soils, units of cm3/cm3\n   * optional, volumetric water content at 1500 kPa: roughly “permanent wilting point” for most plants, units of cm3/cm3\n\nSoil properties must be described, in order, via vars argument. The API does not use logical names but column ordering must follow: sand, silt, clay, bulk density, volumetric water content at 33kPa (1/3 bar), and volumetric water content at 1500kPa (15 bar).\n\n## Background and Practical Applications\n\nFrom an engineering context, predicting soil hydraulic parameters, used to model flow and transport, and subsequently calculating lateral effect distances has historically been time consuming. The current processes used to access authoritative soils data, predict hydraulic parameters, and subsequently calculate lateral effects distances (see Figure 1) require a significant commitment of time from hydraulic engineers. ROSETTA hydraulic outputs included in the web service and API include output parameters of importance for engineering, agronomic, and climate modeling applications.\n\n* Figure 1 - Lateral Effects Diagram\n![Figure 1: Lateral Effects Diagram](https://github.com/ncss-tech/ROSETTA-docs/blob/main/static-figures/lateral%20effects.png)\n\nROSETTA hydraulic parameters are also used in a variety of other ways including:\n   * Modeling changes in soil properties caused by use and management and their effects on soil hydraulic parameters\n   * HYDRUS-3D Simulation of Soil Water Dynamics in Drip-Irrigated Settings\n   * Land Surface Modeling\n   * Agroecosystem models\n   * regional and global climate models, and \n   * Numerical weather prediction models \n\nA simplified version of ROSETTA is available as a web service and accepts user input soils parameters that can be manually inserted or pasted from an external table of soil parameters. The web service can be found [here](https://www.handbook60.org/rosetta/). An example of the ROSETTA web service interface is shown in Figure 2 below.\n\n* Figure 2 - Web Service Interface of ROSETTA example\n![Example: ROSETTA Web Service](https://github.com/ncss-tech/ROSETTA-docs/blob/main/static-figures/Rosetta_web%20service.png)\n\nThrough the ROSETTA REST API, a “proof of concept” python script can be used in IDLE to automate things and avoid the manual web interface. IDLE is python’s integrated development environment and comes with ArcPro however, python is a universal language and can be used in many different applications.\n\nThere are many options for using the ROSETTA REST API. Two methods will be explored here. One method is to query the authoritative soils data and run the ROSETTA predictions simultaneously. Another method is to place an existing soils input table into the script and run the ROSETTA predictions. There are pros and cons of using each method. \n\n### Option 1 - Query the authoritative soils data and run the ROSETTA predictions simultaneously in Python\n\n```{python eval = FALSE}\n\"\"\"\nProof-of-concept for generating soil hydraulic parameters using\nSDMDataAccess and the Rosetta web api.\n\n\"\"\"\nimport requests\nimport sys\nfrom typing import List\n\n\ndef rosetta_url(rosetta_version: int) -\u003e str:\n    return f\"http://www.handbook60.org/api/v1/rosetta/{rosetta_version}\"\n\n\ndef query(areasymbol: str) -\u003e str:\n    return f\"\"\"\n\t\tSELECT\n                           areasymbol,\n                           muname,\n\t\t           musym,\n\t\t           mapunit.mukey,\n                           component.cokey\n\t\t\t   compname,\n\t\t\t   comppct_r,\n\t\t\t   chorizon.hzname,\n\t\t\t   chorizon.hzdept_r,\n\t\t\t   chorizon.hzdepb_r,\n\t\t\t   chorizon.sandtotal_r,\n\t\t\t   chorizon.silttotal_r,\n\t\t\t   chorizon.claytotal_r,\n\t\t\t   chorizon.dbthirdbar_r,\n\t\t\t   chorizon.wthirdbar_r / 100   AS wthirdbar_decimal,\n\t\t\t   chorizon.wfifteenbar_r / 100 AS wfifteenbar_decimal\n\t\tFROM    (legend\n\t\tINNER JOIN (mapunit\n\t\tINNER JOIN component\n\t\tON mapunit.mukey = component.mukey)\n\t\tON legend.lkey = mapunit.lkey)\n\t\tINNER JOIN chorizon\n\t\tON component.cokey = chorizon.cokey\n\t\tWHERE  comppct_r \u003e= 10 AND legend.areasymbol LIKE '{areasymbol}'\n    \"\"\"\n\n\ndef request_ssurgo_tabular(areasymbol: str) -\u003e List[List]:\n\n    url = \"https://SDMDataAccess.sc.egov.usda.gov/Tabular/post.rest\"\n    params = {\"format\": \"JSON+COLUMNNAME\", \"query\": query(areasymbol)}\n    r = requests.post(url, data=params)\n\n    if not r.ok:\n        print(f\"Error!\\nStatus code: {r.status_code}\\nMessage:\\n{r.text}\")\n        sys.exit()\n\n    return r.json()[\"Table\"]\n\n\ndef main():\n    rosetta_version = 2\n    area_symbol = \"SD%\"\n\n    print(f\"Requesting SSURGO data for {area_symbol} ...\")\n    ssurgo_data = request_ssurgo_tabular(area_symbol)\n    print(\"Success!\")\n\n    # this next line assumes the fields sa, si, cl, bd, th33, th1500 were at\n    # the end of the ssurgo SELECT (and in that order)\n    rosetta_input = [row[-6:] for row in ssurgo_data[1:]]\n\n    print(\"Requesting Rosetta estimates ...\")\n    r = requests.post(rosetta_url(rosetta_version), json={\"X\": rosetta_input})\n\n    if not r.ok:\n        print(f\"Error!\\nStatus code: {r.status_code}\\nMessage:\\n{r.text}\")\n        sys.exit()\n    print(\"Success!\")\n\n    # We are done. Now it is just a question of what to do with the results.\n    # Here I dump everything to csv\n\n    rosetta_header = \"thr ths log10_alpha_(1/cm) log10_npar log_Ksat_(cm/d)\".split()\n    import csv\n\n    with open(\"SDA_ROSETTA_results.csv\", \"w\", newline=\"\") as csvfile:\n        writer = csv.writer(csvfile)\n        writer.writerow(ssurgo_data[0] + rosetta_header + [\"model_code\"])\n        for a, b, c in zip(\n            ssurgo_data[1:], r.json()[\"van_genuchten_params\"], r.json()[\"model_codes\"]\n        ):\n            writer.writerow(a + b + [c])\n\n\nif __name__ == \"__main__\":\n    main()\n\n\n\n### Option 2 - Use an existing soils input data table to run ROSETTA predictions in Python\n\nfrom typing import List, Union                                                           \nimport requests                                                                          \n                                                                                         \nDATA = {                                                                                 \n    \"X\": [                                                                               \n        [49, 7.0, 44, 0.99, 0.29011, 0.0261],                                            \n        [42, 30, 28, 1.78, 0.2434, 0.09031],                                             \n        [30, 46, 24, 1.02],                                                              \n        [\"30\", \"46\", \"24\", \"1.02\"],                                                      \n        [34, 38, 28, 1.23, 0.21066, \"BAD\"],                                              \n        [22, 43, 35, 1.56, 0.16495, 0.02243],                                            \n        [85, 9.0, 6.0, 1.08, -99, 0.07483],                                              \n        [31, 44, 25, 1.44, 0.1977, 0.09442],                                             \n        # next entry lacks  minimal required sa, si, cl data                             \n        [12, 21, \"NAN\", 1.02, 0.18889, 0.00821],                                         \n        [48, 11, 41, 1.80, 0.2677, 0.12446],                                             \n        [82, 2.2, 16, 1.58, 0.21149, 0.12008],                                           \n        [None, None, None, None, None, None],                                            \n        [84, 16, 0.0, 1.08, 0.17206, 0.023],                                             \n        [71, 24, 5.0, 1.88, 0.28051, 0.12799],                                           \n        # next entry sa, si, cl are out of bounds, sum \u003e\u003e 100                            \n        [142, 33, 25, 0.73, 0.22333, 0.12299],                                           \n        [39, 22, 39, 0.68, 0.21911, 0.00119],                                            \n    ]                                                                                    \n}                                                                                        \n                                                                                         \n                                                                                         \ndef url(version: int) -\u003e str:                                                            \n    return f\"http://www.handbook60.org/api/v1/rosetta/{version}\"                         \n                                                                                         \ndef to_nan(hydparams: List[Union[float, None]]) -\u003e List[float]:                          \n    \"\"\"covert any None parameter values to nan\"\"\"                                        \n    return [v if v is not None else float(\"nan\") for v in hydparams]                     \n                                                                                         \ndef to_linear(hydparams: List[float]) -\u003e List[float]:                                    \n    \"\"\"convert alp, npar, ksat to linear values.\"\"\"                                      \n    hydparams[2:] = [10 ** v for v in hydparams[2:]]                                     \n    return hydparams                                                                     \n                                                                                         \n                                                                                         \ndef pretty_print(parameters: List[List[float]], codes: List[int]) -\u003e str:                   \n    out = (\"{:\u003e10}\" * 6).format(*\"code thr ths alpha npar ksat\".split())                 \n    out += \"\\n\"                                                                          \n    fmt = \"{:10}\" + \"{:10.5f}\" * 5 + \"\\n\"                                                \n    for params, code in zip(parameters, codes):                                          \n        out += fmt.format(code, *params)                                                 \n    out += \"\\nUnits are alp = 1/cm, ksat = cm/d\\n\"                                       \n    return out                                                                           \n                                                                                         \n                                                                                         \nr = requests.post(url(version=2), json=DATA)\n\nif r.ok:                                                                                 \n    params = [to_nan(row) for row in r.json()[\"van_genuchten_params\"]]                   \n    params = [to_linear(row) for row in params]                                          \n    print(pretty_print(params, r.json()[\"model_codes\"]))                                 \nelse:                                                                                    \n    print(r.status_code)                                                                 \n    print(r.text)\n```\n\n## ROSETTA API Notes\n\n### URL:\n\nhttps://www.handbook60.org/api/v1/rosetta/{int:v}\n\n\nwhere\n\nv = 1, 2, or 3\n\n\ne.g.:\n\nhttps://www.handbook60.org/api/v1/rosetta/3\n\n(Note: when making a request using the python Requests library, I had to use “http” rather than “https”. Not sure why.)\n\n### JSON data\n\nThe POST request expects a json payload with the form\n\n{‘X’: data}\n\nwhere data is a list of lists,  [[,,,],[,,,],[,,,] … ]\n\nEach sublist must be one of the following:\n                             \nData                                                                                                             (Also known as)\n [sand%, silt%, clay%]                      (model code 2)                           \n [sand%, silt%, clay%, rho_b]               (model code 3)                                                         \n [sand%, silt%, clay%, rho_b, th33]         (model code 4)                                                        \n [sand%, silt%, clay%, rho_b, th33, th1500] (model code 5)                           \n\nwhere:                                                                                   \n                                                                                        \n sand%, silt%, and clay%       are the soil separates (sum to ~100)                           \n rho_b    is soil bulk density (gm/cm3)                                                    \n   th33    is the soil volumetric water content at 33 kPa                                    \n   th1500   is the  soil volumetric water content at 1500 kPa  \n\n#### E.g., the json payload might be\n\n{‘X’: [[30,40.5,29.5,1.6],[10,50,40],[90,5,5,1.7,0.22,0.09]]}\n\nNote that even if there is only one sublist, ‘X’ still needs to be 2D list:\n\n {‘X’: [[30,40.5,29.5,1.6]]}\n\n### Returned values\n\nThe returned json has the form\n\n{“van_genuchten_params”: [[,,,,],[,,,,],...],\n “model_codes”: [,, …],\n “rosetta_version”: int\n}\n\nEach sublist in “van_genucthen_params”  is\n\n[theta_r, theta_s, log10(alpha), log10(npar), log10(ksat)]\n\nwhere\n\ntheta_r  : residual volumetric water content                                            \ntheta_s  : saturated volumetric water content                                           \nalpha       : retention shape parameter (1/cm)                                                       \nnpar          : retention shape parameter                                                              \nksat        : saturated hydraulic conductivity (cm/day)\n\n“model_codes” is the list of model codes used to predict the corresponding entry in “van_genuchten_params”\n\n“rosetta_version” is the Rosetta version\n\n\n### An example using curl:\n\ncurl -X POST -H \"Content-Type:application/json\" -d '{\"X\": [[50,40,10,1.6,0.25],[10,40,50,1.5,0.2]]}' \"https://www.handbook60.org/api/v1/rosetta/3\"\n\n{\"model_codes\": [4, 3], \"rosetta_version\": 3, \"van_genuchten_params\": [[0.06930329923825358, 0.3554805457584735, -2.0910869111740067, 0.13999104372677112, 1.1086406024382627], [0.12952613311555153, 0.43802529604640894, -2.1426087306876362, 0.10828373362008699, 0.6976299524746705]]}\n\n\n\n\n### An example using python requests:\n```{python eval = FALSE}\nimport requests                                                                             \n                                                                                         \nDATA = {                                                                                 \n    \"X\": [                                                                               \n        [49, 7.0, 44, 0.99, 0.29011, 0.0261],                                            \n        [42, 30, 28, 1.78, 0.2434, 0.09031],                                             \n        [30, 46, 24, 1.02],                                                              \n    ]                                                                                    \n}                                                                                        \n                                                                                         \n                                                                                         \ndef url(version: int) -\u003e str:                                                            \n    return f\"http://www.handbook60.org/api/v1/rosetta/{version}\"                         \n                                                                                         \nr = requests.post(url(version=2), json=DATA)                                             \n                                                                                         \nif r.ok:                                                                                 \n    print(r.json())                                                                      \nelse:                                                                                    \n    print(r.status_code)                                                                    \n    print(r.text)\n```\n\n\n### Results:\n```\n{'model_codes': [5, 5, 3], 'rosetta_version': 2, 'van_genuchten_params': [[0.03626029823435693, 0.5130283664640276, -2.0560562191308946, 0.14028088599077657, 1.9844066153092994], [0.04371623299088531, 0.3216468185313934, -2.160978983929374, 0.13509126645704977, 0.7097915645849571], [0.0800992063209251, 0.5159619107502098, -2.060414700720488, 0.13422539000745515, 1.957106692448703]]}\n```\n\n## Versioning\n\n(ROSETTA 1) ROSETTA: a computer program for estimating soil hydraulic parameters with hierarchical pedotransfer functions - Schaap, et al(https://www.ars.usda.gov/arsuserfiles/20360500/pdf_pubs/P1765.pdf)\n\n(ROSETTA 2) Comparison of Models for Indirect Estimation of Water Retention and Available Water in Surface Soils - Schaap, et al. This NRCS version is called v 1.3 in the software the engineers currently have. This version identifies both the top and bottom of soil layers and utilizes these depths in the model predictions.\n\n(ROSETTA3) Weighted recalibration of the Rosetta pedotransfer model with improved estimates of hydraulic parameter distributions and summary statistics (Rosetta3) - Zhang, Schaap\n\nROSETTA Version 1 is the original. Version 3 is the newest.  Version 2 is currently what the engineers use to estimate the hydraulic parameters used in LE equations. This version has been added which is a bit different from version 1 and 3. Additionally, the new web service and API allow logarithmic or linear output parameters to be returned. \n\n## Testing and Validation \n\nFor testing and validation purposes a \"test\" dataset must be created and used to predict hydraulic output parameters for each version of the ROSETTA model.\n\nThe following query can be used in [Soil Data Access](https://sdmdataaccess.nrcs.usda.gov/Query.aspx) to assemble a test dataset of the soil parameters used in the ROSETTA model:\n\n```{SQL eval = FALSE}\n\n\"SELECT areasymbol, areaname, musym, muname, mapunit.mukey, component.cokey, compname, comppct_r, majcompflag, hydricrating, chorizon.hzname, chorizon.hzdept_r,  chorizon.hzdepb_r, chorizon.om_r, chorizon.ksat_r AS Ksat_um_per_sec, chorizon.sandtotal_r, chorizon.silttotal_r, chorizon.claytotal_r, chorizon.dbthirdbar_r, chorizon.wthirdbar_r / 100   AS wthirdbar_decimal, chorizon.wfifteenbar_r / 100 AS wfifteenbar_decimal\n\nFROM legend\n\nINNER JOIN mapunit ON legend.lkey=mapunit.lkey AND LEFT (areasymbol, 2) IN  ('MN', 'SD', 'ND', 'IA')\nINNER JOIN component ON mapunit.mukey=component.mukey AND hydricrating = 'Yes' AND majcompflag = 'Yes'\nLEFT OUTER JOIN chorizon ON component.cokey=chorizon.cokey\"\n```\n\n## Future Projects\nLooking to the future, We're exploring ways to automate the other puzzle piece to lateral effects distance determination which is the soil Hydrogeomorphic wetland classification into a web service that could be “called” along with the authoritative soil data.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fncss-tech%2Frosetta-docs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fncss-tech%2Frosetta-docs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fncss-tech%2Frosetta-docs/lists"}