{"id":64156,"name":"Easy-ERA5-Trck","description":"A super lightweight Lagrangian model for calculating millions of trajectories using ERA5 data.","url":"https://github.com/lzhenn/easy-era5-trck","last_synced_at":"2026-04-05T18:01:59.167Z","repository":{"id":41402112,"uuid":"307945984","full_name":"lzhenn/easy-era5-trck","owner":"lzhenn","description":"A super lightweight Lagrangian model for calculating millions of trajectories using ERA5 data","archived":false,"fork":false,"pushed_at":"2025-08-18T03:15:40.000Z","size":36980,"stargazers_count":43,"open_issues_count":0,"forks_count":13,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-03-25T12:41:17.114Z","etag":null,"topics":["era5","lagrangian","multiprocessing","python","trajectory"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lzhenn.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-10-28T08:04:54.000Z","updated_at":"2026-01-05T19:51:21.000Z","dependencies_parsed_at":"2025-09-02T08:32:46.830Z","dependency_job_id":"8479335a-3ca9-49e4-b576-1e23227dfab3","html_url":"https://github.com/lzhenn/easy-era5-trck","commit_stats":null,"previous_names":["novarizark/easy-era5-trck"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/lzhenn/easy-era5-trck","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lzhenn%2Feasy-era5-trck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lzhenn%2Feasy-era5-trck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lzhenn%2Feasy-era5-trck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lzhenn%2Feasy-era5-trck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lzhenn","download_url":"https://codeload.github.com/lzhenn/easy-era5-trck/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lzhenn%2Feasy-era5-trck/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31288350,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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"}},"owner":{"login":"lzhenn","name":"Zhenning Li","uuid":"13349484","kind":"user","description":"Wind extinguishes a candle but energizes fire.","email":"","website":"https://lzhenn.github.io/","location":"Hong Kong","twitter":null,"company":"HKUST","icon_url":"https://avatars.githubusercontent.com/u/13349484?u=bd19b76fd8d608418ea49c07f7a7f278d2166da7\u0026v=4","repositories_count":62,"last_synced_at":"2024-06-11T15:53:15.306Z","metadata":{"has_sponsors_listing":false},"html_url":"https://github.com/lzhenn","funding_links":[],"total_stars":135,"followers":104,"following":81,"created_at":"2023-02-15T06:03:04.154Z","updated_at":"2024-06-11T15:53:19.588Z","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lzhenn","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lzhenn/repositories"},"packages":[],"commits":{"id":1256356,"full_name":"lzhenn/easy-era5-trck","default_branch":"master","total_commits":42,"total_committers":2,"total_bot_commits":0,"total_bot_committers":0,"mean_commits":21.0,"dds":0.04761904761904767,"past_year_total_commits":2,"past_year_total_committers":1,"past_year_total_bot_commits":0,"past_year_total_bot_committers":0,"past_year_mean_commits":2.0,"past_year_dds":0.0,"last_synced_at":"2026-04-03T17:01:20.314Z","last_synced_commit":"5710cca979ff3933a8f5d8cfb5479193ab1232a4","created_at":"2023-04-11T14:35:04.886Z","updated_at":"2026-04-03T17:01:08.903Z","committers":[{"name":"novarizark","email":"novarizark@gmail.com","login":"lzhenn","count":40},{"name":"Junbin Wang","email":"44496598+WanJubing","login":"WanJubing","count":2}],"past_year_committers":[{"name":"Novarizark","email":"novarizark@gmail.com","login":"lzhenn","count":2}],"commits_url":"https://commits.ecosyste.ms/api/v1/hosts/GitHub/repositories/lzhenn%2Feasy-era5-trck/commits","host":{"name":"GitHub","url":"https://github.com","kind":"github","last_synced_at":"2026-04-05T00:00:09.419Z","repositories_count":6211116,"commits_count":924747007,"contributors_count":35739393,"owners_count":1144292,"icon_url":"https://github.com/github.png","host_url":"https://commits.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://commits.ecosyste.ms/api/v1/hosts/GitHub/repositories"}},"issues_stats":{"full_name":"lzhenn/easy-era5-trck","html_url":"https://github.com/lzhenn/easy-era5-trck","last_synced_at":"2026-01-14T02:00:53.322Z","status":"error","issues_count":0,"pull_requests_count":3,"avg_time_to_close_issue":null,"avg_time_to_close_pull_request":126561.66666666667,"issues_closed_count":0,"pull_requests_closed_count":3,"pull_request_authors_count":2,"issue_authors_count":0,"avg_comments_per_issue":null,"avg_comments_per_pull_request":0.0,"merged_pull_requests_count":3,"bot_issues_count":0,"bot_pull_requests_count":0,"past_year_issues_count":0,"past_year_pull_requests_count":0,"past_year_avg_time_to_close_issue":null,"past_year_avg_time_to_close_pull_request":null,"past_year_issues_closed_count":0,"past_year_pull_requests_closed_count":0,"past_year_pull_request_authors_count":0,"past_year_issue_authors_count":0,"past_year_avg_comments_per_issue":null,"past_year_avg_comments_per_pull_request":null,"past_year_bot_issues_count":0,"past_year_bot_pull_requests_count":0,"past_year_merged_pull_requests_count":0,"created_at":"2023-05-09T10:59:46.225Z","updated_at":"2026-01-14T02:00:53.322Z","repository_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/lzhenn%2Feasy-era5-trck","issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/lzhenn%2Feasy-era5-trck/issues","issue_labels_count":{},"pull_request_labels_count":{},"issue_author_associations_count":{},"pull_request_author_associations_count":{"CONTRIBUTOR":2,"OWNER":1},"issue_authors":{},"pull_request_authors":{"WanJubing":2,"lzhenn":1},"host":{"name":"GitHub","url":"https://github.com","kind":"github","last_synced_at":"2026-04-03T00:00:08.051Z","repositories_count":14065016,"issues_count":34433358,"pull_requests_count":112491235,"authors_count":11220102,"icon_url":"https://github.com/github.png","host_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories","owners_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/owners","authors_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors"},"past_year_issue_labels_count":{},"past_year_pull_request_labels_count":{},"past_year_issue_author_associations_count":{},"past_year_pull_request_author_associations_count":{},"past_year_issue_authors":{},"past_year_pull_request_authors":{},"maintainers":[{"login":"lzhenn","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/lzhenn"}],"active_maintainers":[]},"events":{"total":{"WatchEvent":2,"PushEvent":2,"ForkEvent":1},"last_year":{"WatchEvent":1,"PushEvent":2,"ForkEvent":1}},"keywords":["era5","lagrangian","multiprocessing","python","trajectory"],"dependencies":[{"ecosystem":"pypi","filepath":"requirements.txt","sha":null,"kind":"manifest","created_at":"2025-09-02T08:32:41.984Z","updated_at":"2025-09-02T08:32:41.984Z","repository_link":"https://github.com/lzhenn/easy-era5-trck/blob/master/requirements.txt","dependencies":[{"id":24956717299,"package_name":"attrs","ecosystem":"pypi","requirements":"\u003e=21.2.0","direct":true,"kind":"runtime","optional":false},{"id":24956717300,"package_name":"certifi","ecosystem":"pypi","requirements":"\u003e=2020.12.5","direct":true,"kind":"runtime","optional":false},{"id":24956717301,"package_name":"cffi","ecosystem":"pypi","requirements":"\u003e=1.14.5","direct":true,"kind":"runtime","optional":false},{"id":24956717302,"package_name":"cfgrib","ecosystem":"pypi","requirements":"\u003e=0.9.9.0","direct":true,"kind":"runtime","optional":false},{"id":24956717971,"package_name":"cftime","ecosystem":"pypi","requirements":"\u003e=1.4.1","direct":true,"kind":"runtime","optional":false},{"id":24956718979,"package_name":"click","ecosystem":"pypi","requirements":"\u003e=8.0.1","direct":true,"kind":"runtime","optional":false},{"id":24956718980,"package_name":"eccodes","ecosystem":"pypi","requirements":"\u003e=1.3.2","direct":true,"kind":"runtime","optional":false},{"id":24956720847,"package_name":"findlibs","ecosystem":"pypi","requirements":"\u003e=0.0.2","direct":true,"kind":"runtime","optional":false},{"id":24956720881,"package_name":"netCDF4","ecosystem":"pypi","requirements":"\u003e=1.5.6","direct":true,"kind":"runtime","optional":false},{"id":24956721039,"package_name":"numpy","ecosystem":"pypi","requirements":"\u003e=1.20.3","direct":true,"kind":"runtime","optional":false},{"id":24956721040,"package_name":"pandas","ecosystem":"pypi","requirements":"\u003e=1.2.4","direct":true,"kind":"runtime","optional":false},{"id":24956721041,"package_name":"pycparser","ecosystem":"pypi","requirements":"\u003e=2.20","direct":true,"kind":"runtime","optional":false},{"id":24956721042,"package_name":"python-dateutil","ecosystem":"pypi","requirements":"\u003e=2.8.1","direct":true,"kind":"runtime","optional":false},{"id":24956721043,"package_name":"pytz","ecosystem":"pypi","requirements":"\u003e=2021.1","direct":true,"kind":"runtime","optional":false},{"id":24956721044,"package_name":"six","ecosystem":"pypi","requirements":"\u003e=1.16.0","direct":true,"kind":"runtime","optional":false},{"id":24956721045,"package_name":"xarray","ecosystem":"pypi","requirements":"\u003e=0.17.0","direct":true,"kind":"runtime","optional":false}]}],"score":4.454347296253507,"created_at":"2023-09-18T12:26:43.407Z","updated_at":"2026-04-05T18:01:59.169Z","avatar_url":"https://github.com/lzhenn.png","language":"Python","category":"Emissions","sub_category":"Emission Observation and Modeling","monthly_downloads":0,"total_dependent_repos":0,"total_dependent_packages":0,"readme":"\n# Easy-ERA5-Trck\n\n- [Easy-ERA5-Trck](#easy-era5-trck)\n    + [Galleries](#galleries)\n    + [Install](#install)\n    + [Usage](#usage)\n    + [Repository Structure](#repository-structure)\n    + [Module Files](#module-files)\n    + [Version iteration](#version-iteration)\n\n\n**Disclaimer: The open-source tool utilizes a trajectory calculation methodology based on nearest-neighbor interpolation and first-guess velocity estimation to optimize computational efficiency. \nThis tool does not account for atmospheric diffusion or convection processes. \nNo warranties, express or implied, are provided regarding the accuracy, reliability, or suitability of the results generated by this tool. \nThe tool is not intended for scientific or professional applications unless the user independently verifies the results through rigorous validation procedures.**\n\n**For accurate trajectory calculations, users are directed to consult peer-reviewed methodologies, such as those described in the publication available at http://journals.ametsoc.org/doi/abs/10.1175/BAMS-D-14-00110.1, or to employ established professional models, such as NOAA HYSPLIT. \nThe developers and contributors of this tool disclaim any liability for damages, losses, or consequences arising from the use of this tool or reliance on its outputs.**\n\n\n\n\nEasy-ERA5-Trck is a super lightweight Lagrangian model for calculating thousands (even millions) of trajectories simultaneously and efficiently using ERA5 data sets. \nIt can implement super simplified equations of 3-D motion to accelerate integration, and use python multiprocessing to parallelize the integration tasks.\nDue to its simplification and parallelization, Easy-ERA5-Trck performs great speed in tracing massive air parcels, which makes **areawide** tracing possible.\n\nAnother version using WRF output to drive the model can be found [here](https://github.com/Novarizark/easy-wrf-trck). \n\n**Any question, please contact Zhenning LI (zhenningli91@gmail.com)**\n\n### Galleries\n\n#### Tibetan Plateau Air Source Tracers\n\u003cimg src=\"https://raw.githubusercontent.com/Novarizark/easy-era5-trck/master/gallery/tp.source.result.gif\" alt=\"tp_tracer\" align=center /\u003e\n\n#### Tibetan Plateau Air Source Tracers (3D)\n\u003cimg src=\"https://github.com/Novarizark/easy-era5-trck/blob/master/gallery/tp.source.result.3d.gif?raw=true\" alt=\"tp_tracer_3d\" align=center /\u003e\n\n### Install\n\nIf you wish to run easy-era5-trck using `grib2` data, Please first install [ecCodes](https://confluence.ecmwf.int/display/ECC/ecCodes+Home).\n\nPlease install python3 using Anaconda3 distribution. [Anaconda3](https://www.anaconda.com/products/individual) with python3.8 has been fully tested, lower version of python3 may also work (without testing).\n\nNow, we recommend to create a new environment in Anaconda and install the `requirements.txt`:\n\n```bash\nconda create -n test_era5trck python=3.8\nconda activate test_era5trck\npip install -r requirements.txt\n```\n\nIf everything goes smoothly, first `cd` to the repo root path, and run `config.py`:\n\n```bash\npython3 config.py\n```\n\nThis will convey fundamental configure parameters to `./conf/config_sys.ini`.\n\n### Usage\n\n#### test case\nWhen you install the package ready. You may first want to try the test case. `config.ini` has been set for testcase, which is a very simple run:\n``` python\n[INPUT]\ninput_era5_case = ./testcase/\ninput_parcel_file=./input/input.csv\n\n[CORE]\n# timestep in min\ntime_step = 30\nprecession = 1-order\n# 1 for forward, -1 for backward\nforward_option = -1\n# for forward, this is the initial time; otherwise, terminating time\nstart_ymdh = 2015080212\n# integration length in hours\nintegration_length = 24\n# how many processors are willing to work for you\nntasks = 4\n# not used yet\nboundary_check = False\n\n[OUTPUT]\n# output format, nc/csv, nc recommended for large-scale tracing\nout_fmt = nc\nout_prefix = testcase\n# output frequency in min\nout_frq = 60\n# when out_fmt=csv, how many parcel tracks will be organized in a csv file.\nsep_num = 5000\n\n```\nWhen you type `python3 run.py`, Easy-ERA5-Trck will uptake the above configurations, by which the ERA5 UVW data in `./testcase` will be imported for driving the Lagrangian integration.\n\nNow you will see your workers are dedicated to tracing the air parcels. After several seconds, if you see something like:\n``` bash\n2021-05-31 17:32:14,015 - INFO : All subprocesses done.\n2021-05-31 17:32:14,015 - INFO : Output...\n2021-05-31 17:32:14,307 - INFO : Easy ERA5 Track Completed Successfully!\n```\nCongratulations! The testcase works smoothly on your machine!\n\nNow you could check the output file in `./output`, named as `testcase.I20150802120000.E20150801120000.nc|csv`, which indicates the initial time and endding time. For backward tracing, I \u003e E, and vice versa.\n\nYou could choose output files as plain ascii csv format or netCDF format (Recommended). netCDF format output metadata looks like:\n``` bash\n{\ndimensions:\n    time = 121 ;\n    parcel_id = 413 ;\nvariables:\n    double xlat(time, parcel_id) ;\n        xlat:_FillValue = NaN ;\n    double xlon(time, parcel_id) ;\n        xlon:_FillValue = NaN ;\n    double xh(time, parcel_id) ;\n        xh:_FillValue = NaN ;\n    int64 time(time) ;\n        time:units = \"hours since 1998-06-10 00:00:00\" ;\n        time:calendar = \"proleptic_gregorian\" ;\n    int64 parcel_id(parcel_id) ;\n}\n```\n\n#### setup your case\nCongratulation! After successfully run the toy case, of course, now you are eager to setup your own case. \nFirst, build your own case directory, for example, in the repo root dir:\n```bash\nmkdir mycase\n```\nNow please make sure you have configured **[ECMWF CDS API](https://cds.climate.copernicus.eu/api-how-to)** correctly, both in your shell environment and python interface.\n\nNext, set `[DOWNLOAD]` section in `config.ini`  to fit your desired period, levels, and region for downloading.\n\n```python\n[DOWNLOAD]\nstore_path=./mycase/\nstart_ymd = 20151220\nend_ymd = 20160101\npres=[700, 750, 800, 850, 900, 925, 950, 975, 1000]\n\n# eara: [North, West, South, East]\narea=[-10, 0, -90, 360]\n# data frame frequency: recommend 1, 2, 3, 6. \n# lower frequency will download faster but less accurate in tracing\nfreq_hr=3\n```\nHere we hope to download 1000-700 hPa data, from 20151220 to 20160101, 3-hr temporal frequency UVW data from ERA5 CDS.\n\n`./utlis/getERA5-UVW.py` will help you to download the ERA5 reanalysis data for your case, in daily file with `freq_hr` temporal frequency.\n```bash\ncd utils\npython3 getERA5-UVW.py\n```\n\nWhile the machine is downloading your data, you may want to determine the destinations or initial points of your targeted air parcels.\n`./input/input.csv`: This file is the default file prescribing the air parcels for trajectory simulation. Alternatively, you can assign it by `input_parcel_file` in `config.ini`.\n\nThe format of this file:\n\n```\nairp_id, init_lat, init_lon, init_h0 (hPa)\n```\nFor forward trajectory, the init_{lat|lon|h0} denote initial positions; while for backward trajectory, they indicate ending positions.\nYou can write it by yourself. Otherwise, there is also a utility `./utils/take_box_grid.py`, which will help you to take air parcels in a rectanguler domain.\n\nplese also set other sections in `config.ini` accordingly, now these air parcels are waiting your command `python3 run.py` to travel the world!\n\nBesides, `./utils/control_multi_run.py` will help you to run multiple seriels of the simulation. There are some postprocessing scripts for visualization in `post_process`, you may need to modify them to fit your visualization usage.\n\n\n### Repository Structure\n\n#### run.py\n`./run.py`: Main script to run the Easy-ERA5-Trck. \n\n\n#### conf\n* `./conf/config.ini`: Configure file for the model. You may set ERA5 input file, input frequency, integration time steps, and other settings in this file.\n* `./conf/config_sys.ini`: Configure file for the system, generate by run `config.py`. \n* `./conf/logging_config.ini`: Configure file for logging module. \n\n#### core\n* `./core/lagrange.py`: Core module for calculating the air parcels Lagrangian trajectories.\n\n#### lib\n* `./lib/cfgparser.py`: Module file containing read/write method of the `config.ini`\n* `./lib/air_parcel.py`: Module file containing definition of air parcel class and related methods such as march and output.\n* `./lib/preprocess_era5inp.py`: Module file that defines the field_hdl class, which contains useful fields data (U, V, W...) and related method, including ERA5 grib file IO operations.\n* `./lib/utils.py`: utility functions for the model.\n\n#### post_process\nSome visualization scripts.\n\n#### utils\nUtils for downloading, generating `input.csv`, etc.\n\n### Version iteration\n\n#### Oct 28, 2020\n* Fundimental pipeline design, multiprocessing, and I/O.\n* MVP v0.01\n\n#### May 31, 2021\n* Major Revision, logging module, and exception treatment\n* test case\n* Major documentation update\n* Utility for data downloading\n* Utility for taking grids in a box \n* Basic functions done, v0.10\n\n#### Jun 09, 2021\n* The automatic detection of longitude range is added, allowing users to adopt two different ranges of longitude: [-180°, 180°] or [0°, 360°].\n* Currently, if you want to use the [-180°, 180°] data version, you can only set ntasks = 1 in the config.ini file.\n\n#### Oct 19, 2021\n* Modify `requirements.txt` to fit updated version of libs.\n\n#### Jun 24, 2022\n* Add Administrative Grid and sparse matrix match utils: `./utils/assign_nodes_to_city.py` and `./utils/assign_sparse_nodes.py`.\n","funding_links":[],"readme_doi_urls":[],"works":{},"citation_counts":{},"total_citations":0,"keywords_from_contributors":[],"project_url":"https://ost.ecosyste.ms/api/v1/projects/64156","html_url":"https://ost.ecosyste.ms/projects/64156"}