This archive contains answers to questions sent to Unidata support through mid-2025. Note that the archive is no longer being updated. We provide the archive for reference; many of the answers presented here remain technically correct, even if somewhat outdated. For the most up-to-date information on the use of NSF Unidata software and data services, please consult the Software Documentation first.
Hello! Thanks for reaching out. First, to address your questions about your GeoJSON data here: We don't currently have any MetPy functionality or any examples for GeoJSON data. However, we do have a contributor working right now on enabling simplified plotting of GeoJSON data within MetPy using GeoPandas (https://geopandas.org/). Separate to that, we do plan to create a few examples of working with data like these in Python in the future. For what you've provided today: as far as I can tell, the JSON you've created here is not a valid "FeatureCollection" and does not follow current GeoJSON specification. A "FeatureCollection" must have members of name "Feature", each containing a "Geometry" member, which your "LineString"s would fall under. Check out https://geojsonlint.com and the Feature > FeatureCollection demo at the top to see a valid representation of this. You can also double-check with the current GeoJSON specification document: https://datatracker.ietf.org/doc/html/rfc7946. So, your generated data here are close and are valid JSON, but are not valid GeoJSON. If you want your current code to do this in a valid way, you can add your LineStrings to a Feature first; here's a brief code example: import geojson lat_1 = [25.5, 25.8, 27.9] lat_2 = [26.5, 26.8, 28.9] lon_1 = [-85, -86, -87.5] lon_2 = [-84, -85, -86.5] my_linestring_1 = geojson.LineString(list(zip(lon_1, lat_1))) my_linestring_2 = geojson.LineString(list(zip(lon_2, lat_2))) my_feature_1 = geojson.Feature(geometry=my_linestring_1) my_feature_2 = geojson.Feature(geometry=my_linestring_2) my_collection = geojson.FeatureCollection([my_feature_1, my_feature_2]) my_geojson = geojson.dumps(my_collection) with open(outfile, 'w') as f: f.write(my_geojson) which results in the following valid GeoJSON, {"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-85, 25.5], [-86, 25.8], [-87.5, 27.9]]}, "properties": {}}, {"type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-84, 26.5], [-85, 26.8], [-86.5, 28.9]]}, "properties": {}}]} This also highlights that you can do all of your GeoJSON specification with only what's built into the geojson package you've obtained from pypi. You don't have to try and construct the GeoJSON yourself. Similarly, if you are comfortable with the pandas DataFrame and Series interfaces, there is a package called GeoPandas (https://geopandas.org/index.html) that gives you this interface for common GIS data formats, including reading and writing GeoJSON. GeoPandas can also give you a much more friendly representation of these data within say a Jupyter Notebook. Can it be better formatted? GeoJSON is a specific subset of JSON, and so has to follow its formatting specifications. It will be somewhat hard to read and has to be formatted this way if you stick with those files. To answer your other question about persisting information between Python functions: there are a few ways you can do this. Variables are "scoped" within Python, which means they are accessed and referenced within various nested levels; further reading available here: https://realpython.com/python-scope-legb-rule/. You can declare a variable within a function to be global using the `global <var>` statement so that you can modify variables outside your function. However, this should be avoided! This can lead to potentially gross bugs, crossed streams, or multiple future headaches. If the tools provided by the GeoJSON or GeoPandas packages aren't accomplishing what you're looking for on their own, then I'd suggest digging a bit deeper and learning how to create your own class. Classes can contain multiple separate functions, just the same as you've laid out your .py files here, but can share properties and information between the different functions without having to modify variables between scopes within Python. There are many different resources out there for learning how to write classes, e.g. the official Python documentation tutorial: https://docs.python.org/3/tutorial/classes.html, though we don't have any of our own thorough materials on this currently. I hope this helps, and don't hesitate to reach back out if there's further ways we can help push this forward! All the best, Drew > Looking at metpy I tried to write a Geojson file with a linestyle (no example > of this). I wanted to ask two major questions: > > First, I produced the following geojson file which is supposed to be 3 line > tracks, like for a hurricane: > > "{\"type\": \"FeatureCollection\", \"features\": [{\"type\": \"LineString\", > \"coordinates\": [[-85.0, 25.5], [-86.0, 25.8], [-87.5, 27.9], [-89, 29.5]]}, > {\"type\": \"LineString\", \"coordinates\": [[-86.0, 26.5], [-87.0, 26.8], > [-88.5, 28.9], [-90, 30.5]]}, {\"type\": \"LineString\", \"coordinates\": > [[-87.0, 27.5], [-88.0, 27.8], [-89.5, 29.9], [-91, 31.5]]}, {\"type\": > \"LineString\", \"coordinates\": [[-88.0, 28.5], [-89.0, 28.8], [-90.5, > 30.9], [-92, 32.5]]}, {\"type\": \"LineString\", \"coordinates\": [[-89.0, > 29.5], [-90.0, 29.8], [-91.5, 31.9], [-93, 33.5]]}]}" > > Don't know if this looks right and its hard to read. Would like to have > better formatting in either case. > > Question 1: Does the above look like a geojson file created via pypi geojson > and can it be better formatted? > > > I used two test programs, my driver or main program follows: > > --------------------------- test_geojson.py > ______________________________________________ > from datetime import datetime > import geojson_save as traj > > trajectory_format = "geojson" > output_dir = "./trajectories/" > traj.geojson_init(output_dir) > > > for j in range(0, 5): > > lat = [25.5+j, 25.8+j, 27.9+j, 29.5+j] > lon = [-85.0-j, -86.0-j, -87.5-j, -89-j] > pres_mb = [999.0-j, 998.0-j, 997.0-j, 996.0-j] > print(lat) > print(lon) > print(pres_mb) > traj.geojson_write(lat, lon, j) > > print(lat) > my_datetime = datetime.now().strftime("%Y-%m-%d_%H%M%S") > traj.geojson_close(my_datetime) > > ---------------------------- end test_geojson.py > ------------------------------------------------------ > > The above program creates three tracks, like for a fake hurricane. It has a > setup program which I should off removed. I stripped down to just the > following > > > > Question 2: I wanted to have a function to create geojson tracks, I don't > know the best way in python to presist data between function calls. > Like to have a global variable, or static or singleton instance. Can a better > way be done than I use to persist variables between function calls? > > -------------------------- save_geojson.py > ----------------------------------------------------------- > > import os > import geojson > from geojson import Feature, Point, FeatureCollection > import json > > > def geojson_init(output_dir): > print("geojson_initialize... with output to "+output_dir) > geojson_init.write_dir = output_dir # want to persist write_dir or make > static or global > geojson_init.features = [] # want to persist write_dir or make > static or global > > > def geojson_write(lat, lon, j): > print("geojson_initialize...") > > my_linestring = { > 'type': 'LineString', > 'coordinates': [[lon, lat] for lon, lat in zip(lon, lat)] > } > geojson_init.features.append(my_linestring) > > > def geojson_close(file_date): > > my_dir = geojson_init.write_dir > output_file = my_dir + file_date + ".js" > geometries = { > 'type': 'FeatureCollection', > 'features': geojson_init.features > } > > geo_str = json.dumps(geometries) > > # write to a file > with open(output_file, 'w') as f: > f.write(geojson.dumps(geo_str)) > > print("wrote geojson to "+output_file) > > > > ----------------------------------------- end geojson_save.py > ------------------------------- > > So looking for advise to move lat, lon, arrays or list to geojson LineString > features. Also, learn best method to presist data between function > calls. > Ticket Details =================== Ticket ID: MFJ-706941 Department: Support Python Priority: Low Status: Closed =================== NOTE: All email exchanges with Unidata User Support are recorded in the Unidata inquiry tracking system and then made publicly available through the web. If you do not want to have your interactions made available in this way, you must let us know in each email you send to us.