jeffdc / gallformers

The gallformers site
https://www.gallformers.org
Apache License 2.0
15 stars 9 forks source link

How to handle regions #46

Closed Megachile closed 3 years ago

Megachile commented 3 years ago

In a sense, range info is accounted for by host species. If a user knows the host to species, then region is irrelevant. However, at the genus or subgenus level this is not the case. If a user in CA wants to see, for instance, every stem gall on oaks, they're going to get a list that includes dozens of species outside CA. It would be nice to be able to filter those out.

It seems like a problem best handled on the host plant side, since data is usually so incomplete on the gall end. I just can't figure out how we should go about it. I don't want to end up manually region-labeling species at really any scale if I can possible avoid it. DiscoverLife keys and BugGuide do this at the state level, which could work for us if we had a way to automatically associate state-level occurrence records with each plant species. Eg pulling that data from iNat or USDA PLANTS or wherever. That would be the most comprehensive and (if automated) future-proof way to solve the issue, but also the most work-intensive, if it's even reasonably possible. Or we could just manually label the CA endemics and call it good. Any ideas?

jeffdc commented 3 years ago

I think that we can look to expand the data we store with a species to include some geographic range information. This could then apply to a gallformer or a host. Clearly host is the more useful, but at least we would have the future option for any species of gallformer that is more range restricted than the host.

I think that state-level is fine since we have restricted ourselves to US/Canada. Even if we expand to Mexico or northern Caribbean state-level would likely work. I think this approach would run into troubles beyond that range.

We can certainly pull from an data source that has an API.

Proposal:

  1. add a range field to the Admin Host screen
  2. the field will allow 0-n entries from a predetermined list (US States, Canadian Provinces for now)
  3. the field is optional
  4. add the range field to the main Host view screen
  5. if the range is empty, then trigger a back-end process that will call an external API to fetch range info
  6. modify the ID screen to have a range filter that will show the list as in 2. above

Schema Changes

Proposal --- these need more thought and likely research looking into how the proposed USDA API shapes data so that we can easily conform to that.

range (new table)

regions (new table)

Items of research:

Megachile commented 3 years ago

It looks like USDA recently built an API that should definitely be able to provide updated range lists by plant species. It's discussed here, in the issues page of a github for a privately built API that is now deprecated since the USDA replaced it with an official one. I guess this is the documentation that Alex tells me has everything we would need to call from it; he was able to do it successfully.

Megachile commented 3 years ago

I'm not sure I understand the "if" logic of step 5. Why would we want manually entering a range to prevent the site from calling the API?

Megachile commented 3 years ago

Generally I think this would will work just fine. How do you see aggregations of states needing to be handled distinctly?

jeffdc commented 3 years ago

The if logic is in place so that we are not fetching ranges all of the time. Really only if they are empty. The option to manually edit will exist, but I agree that if we hook up to an API it is much better to populate the data that way.

I am not sure about aggregations. We could start with out them but if we think that they will be super useful then we should probably put the effort in up front to figure out how we want them to work.

Megachile commented 3 years ago

I'm just afraid of a user entering a new host and helpfully adding some states where they know the plant occurs, which unbeknownst to them prevents the API from ever running on that plant. It might actually make sense to have the range populate automatically by default, then create a separate page to edit ranges if necessary? It really should not be common for us to need to edit the ranges at all if the API works. I would hope USDA plants is fairly comprehensive.

I can't think of a case where aggregations would be useful on top of state-level species ranges, can you? Doesn't seem worth the bother.

jeffdc commented 3 years ago

Ok that makes sense.

I am unsure of aggregations. I guess state level is fine enough grain for our purposes.

Thinking more I am wondering if finer grained partitioning is more important than aggregations? I maybe biased as to the importance, as here in VA we have a huge variety of plants. This is due to VA being the transition from the Southern US to the Northern US as well as having beaches and alpine habitat. That gets me thinking about things like USDA hardiness zones. Not sure that this would ever matter but better to eliminate it now then have to add it later!

Megachile commented 3 years ago

Yeah, it just seems like anything you might use "New England" for you could just pick a state in New England, etc. I mean, if you want to let people select every state in the broad New England area then we could make sure that you can select more than one state at once? But that isn't so onerous or a common enough use-case to demand a separate button, I think.

As for even finer grained regions, that would definitely be useful--eg in CA, there are tons of species and the list varies substantially from north to south. Lots of states include just a tiny bit of the range of species, which makes their host count look much bigger than it practically is in most places.

The USDA plants API does give county-level occurrence data for each species, although comparing iNat and Plants definitely suggests those county-level records are incomplete. I would certainly feel like I was risking missing something if I filtered by the county level, which our users may not realize.

I suppose we could theoretically use the county-level data to manually build regions within states?

madeleineclaire commented 3 years ago

Where would you display this information and how would it look? That might help narrow down what makes the most sense. For example would you be adding "Range" as a field on the galls' information page? Would it be a visual/map similar to what you see on iNat (minus the red observation dots of course)? Something similar to a range map like in a Sibley bird field guide would be pretty helpful if it was possible.

Selfishly I'd love to be able to pull gall info at the county level. I travel a lot for work in non COVID times and it would be great fun to be able to pull species lists of whats in the areas I'm visiting. I really enjoy that ability on iNat.

mytwocents

Megachile commented 3 years ago

I was thinking it could be one of the basic filters on ID along with host, detachable, and location. You would click the state/province where the observation was made to see only the galls associated with plants known to occur there. Then if we had county data we could offer an additional filter (using the infrastructure we would have to build for #39) for county after the user had selected a state/province.

Listing all the states/counties as text on the page for a host would obviously too much. We could put the maps on the host page, which would just amount to reproducing the USDA plants page for that plant. Not sure if that's worth it.

On a gall page, I am hesitant about even putting up a map because while it's always possible that a gall will occur anywhere its hosts occur, it seems misleading to imply that the gallformer actually occupies that full range. And we just don't have enough data to draw range maps for any but the most commonly observed gallformers.

madeleineclaire commented 3 years ago

Having a map of the host's range on the host page sounds like a good plan as does being able to select state and take it further into a county selection when filtering. Thanks again for putting all of this together. It's going to be great.

jeffdc commented 3 years ago

I am pulling this one out of scope for the work I am doing on #72 and related. This one will have to be tackled later or in parallel if someone else wants to work on it. Thinking about it I do not think that there will be an overlap in the schema changes between this and all the other ones related to #72.

jeffdc commented 3 years ago

I want to revisit this and think about how we tackle it. I feel like there was more discussion RE regions in another issue but I can not locate it. There is #169 which is related but not what I was thinking of. Anyhow...

As a first step I think that we need to make a decision to add some sort of region metadata to galls and/or hosts.

Using government range data has challenges as detailed here: https://bplant.org/blog/5

Megachile commented 3 years ago

At this point I think the question basically comes down to who does the work and how.

If you (or someone else) can code up a way to somehow automatically populate presence/absence data for hosts in each state and province, I think that would be about the best we can reasonably do (county data and possibly other info about hosts are things we could decide to take as well if they are easily accessible in this process but I don't think they should be the main approach). Alex's concerns about the ERA data are valid but IMO not something we need to be at all worried about (especially since they err on the side of inclusion, as I would want to do).

Or we can handle it like season and leave it to the user, but in that case I think we should treat region very broadly, similar to Weld's "Pacific" "Southwest" and "Eastern." That would in a sense reduce the utility of the range function considerably (especially if lots of hosts don't get tagged) but it would at least let us use the site as a substitute for the Weld books.

jeffdc commented 3 years ago

I could basically implement what is outlined above with this data: https://plants.sc.egov.usda.gov/home/downloads

Does not help with Canada or finer grained location. For the display we could group states into regions like you suggest above or we could display each state.

Megachile commented 3 years ago

That's annoying that the data doesn't have Canada. It's displayed in the maps for each species so I figured it would be in the API.

Megachile commented 3 years ago

How difficult would it be to have something like the Bugguide maps, highlighting the states where the plant is present?

jeffdc commented 3 years ago

I have never worked with geo/mapping data or tools so I am unsure as to complexity.

RE the Canada data, I can not get any data from that API that you linked to in an earlier comment. The only data that I can find is those static CSV files that you can download.

There is nothing that responds at https://plants.usda.gov/api.

jeffdc commented 3 years ago

Looking at that USDA site more and analyzing the under the hood API, I would never put any reliance on that inline with our site. It is incredibly poorly constructed and slow. It is a real shame as the data all seems to be there but it is essentially inaccessible other than by browsing their website.

I will look for other API options. The other approach is try and find a data dump of all the data from USDA and use that.

jeffdc commented 3 years ago

There is a 5 year old dump of the data here: https://uofi.app.box.com/v/usdaplants

jeffdc commented 3 years ago

The data in the CSV dump I linked immediately above does not contain range data other than Lower48/Canada/Puerto Rico/US Virgin Islands/Hawaii no state level data.

jeffdc commented 3 years ago

I grabbed the data that bplant.org uses, http://www.nativerevegetation.org/era/ We could use this but it is more complex. It breaks all the plants down by ecoregion. It lists 87 ecoregions (only US data). We would basically need to replicate something like this https://bplant.org/regions.php

jeffdc commented 3 years ago

The workable options after all of this seem to be only 2:

1) We grab the CSV downloads for each state from the USDA website and load that data, only state based granularity 2) We use the same data that bplant uses which provides far better granularity than state level, but comes with the added complexity of having to explain ecoregions to users and having a lookup tool for users to figure out ecoregions

None of these options include any data for Canada. There may be Canada specific data available somewhere but I did not look for it. At this point I think that we should focus on the US and add Canada later.

jeffdc commented 3 years ago

Update on the USDA Plants API: https://github.com/USDA/USDA-APIs/issues/7#issuecomment-846024448

Megachile commented 3 years ago

So I guess we'll wait on that then?

jeffdc commented 3 years ago

Given that they have no timeline and took the old API down without any warning or announcement I would not want to rely on it. I think that we should use of the two approaches that I proposed above.

Megachile commented 3 years ago

Well it seems like option 1 does everything I was hoping for, I don't think ecoregions are worth messing with for us.

jeffdc commented 3 years ago

I am going to begin work on this. Thinking about it more I really think that we should leave the door open for finer grained geographic range info than just state. My research into Oaks in VA has made it very apparent that it can be a very coarse measure indeed. I will still take the approach outline above, but I am going to allow for more flexibility in how I defined the geographic area. We will start with states, but in the future we will be able to refine that down and to support a hierarchy (e.g., Fairfax County is in VA). I will organize my thoughts about the approach and document it here for review before I start on implementation.

jeffdc commented 3 years ago

Here is what I am thinking:

Create a new Place table and related Admin screen with the following data:

To allow for a hierarchy I will create a new table that allows regions to be related to other regions:

This allows for arbitrary nesting of places.

Add a Range field to Host (for now just Host). Range is a reference to one or more Places. If you add a Place that has children, all of those children will automatically be included in the Range. This is manifested in the database as a new range table with the following fields:

Add Places:

Import all of the USDA data for the hosts by state (less Hawaii). This will populate the ranges for matching hosts to the state-level.

Add a range filter to the ID screen. This will be an "above the fold" filter like Location/Detachable.

Megachile commented 3 years ago

So to make sure I'm understanding this correctly: you're making an admin page that will allow users to manually add places, regions, countries, etc, and manually associate them with host plants in the db. This is completely flexible so it will accommodate Mexico, Central American countries, etc as they are added (we have a few now)--we may want to handle those like scales, either leaving them out by default or give a way to easily exclude them--and the only current way we have to handle Canada and county level US data.

Will the USDA import apply only to plants currently listed in the DB or are you just going to grab all the plants they have and create new host records where necessary? If the former we may have to repeat the import periodically to cover new hosts as we add them, so we should think about what that would do to info that may have been manually added in the meantime.

There may also be issues on the import with names not matching, etc--is there a way you can check the names first before we do the full import to see if we can catch any of those in advance?

If you add a Place that has children, all of those children will automatically be included in the Range

Unless I'm misunderstanding this, I don't think this is the behavior people will expect this to have? So for instance if you added a plant that occurs in Mexico and sourthern Texas to "US" then it would include every US county in the range of that plant? Would there be a convenient way to erase or undo things like this, at least?

jeffdc commented 3 years ago

I am proposing that we create a Places Admin page to mange places. Associating to hosts would be done on the current Host admin page (I failed to mention this). Yes we could add non US/Canada stuff all we want and I agree that we want to think about default filters etc.

I expect a lot of challenges with the USDA import. I have not tried anything with it yet but I am sure that there will be a lot of cases where our data does not align and we will need to intervene. My plan is to merge all of the files into one large file where the states are added as a column. This will then make the data more manageable. Then I will run a test to see how many match up to what we have in our DB. I am not sure that we will be able to have a regular process to refresh it without a large investment of time and code. After I start working with it I will know better. I would like to import all of the hosts but need to think about implications. Probably none but just not sure at this time.

RE the parent children stuff. My thinking /writing was not clear let me try again.

If a Host is assigned to a place it will match for that place and any parent of that place. So if I assign the state VA to Q alba then it will match for VA, US, Mid-Atlantic, North America, and any other Place that is in the parental hierarchy for VA.

Megachile commented 3 years ago

If a Host is assigned to a place it will match for that place and any parent of that place.

Yeah parent makes much more sense here than child.

I think it would be ideal to just pull the whole USDA list at once if there are no clear downsides. That will save us a lot of time adding hosts in the future too (especially if you can pull synonyms and common names too?).

Let me know if there's anything I can do to help.

jeffdc commented 3 years ago

My biggest concern with the data import is those hosts that we have that do not match those that are in the USDA list. I do not want to accidentally create duplicates. Once I get the import code written I can dry run it and compute what hosts in our DB do not get matched. This will then let us figure out how to handle those.

I will being in any common names that are in the USDA list. There does not seem to be any synonyms in the data.

jeffdc commented 3 years ago

The USDA data contains more detail than I think we need or want to mess with. In particular it contains a lot of subspecies/variety information. e.g. here is the listing for corn in VA:

The columns are: "Symbol","Synonym Symbol","Scientific Name with Author","State Common Name","Family"

"ZEMA","","Zea mays L.","corn","Poaceae"
"ZEMAM2","","Zea mays L. ssp. mays","corn","Poaceae"
"ZEMAM2","ZEMAE","Zea mays L. ssp. everta (Sturtev.) Zhuk.","","Poaceae"
"ZEMAM2","ZEMAJ","Zea mays L. var. japonica (Van Houtte) Alph. Wood","","Poaceae"
"ZEMAM2","ZEMAT","Zea mays L. var. tunicata Larrañaga ex A. St.-Hil.,","","Poaceae"

Do we need any of this subspecies/variety data?

I am also going to have to parse out the the Scientific Names since they contain the original Author info. Hopefully all cases conform to the same pattern _Genus specificepithet Author ssp Info

Update: Looking at this more we also have to decide how to deal with hybrids. Here is a partial listing for Quercus in VA:

"QUAL","","Quercus alba L.","white oak","Fagaceae"
"QUAL","QUALS","Quercus alba L. var. subcaerulea A.L. Pickens & M.C. Pickens","","Fagaceae"
"QUAL","QUALS2","Quercus alba L. var. subflavea A.L. Pickens & M.C. Pickens","","Fagaceae"
"QUBE","","Quercus ×beadlei Trel. ex Palmer [alba × michauxii]","Beadle oak","Fagaceae"
"QUBE3","","Quercus ×bebbiana C.K. Schneid. [alba × macrocarpa]","hybrid oak","Fagaceae"
"QUBI","","Quercus bicolor Willd.","swamp white oak","Fagaceae"
"QUBU","","Quercus ×bushii Sarg. [marilandica × velutina]","Bush oak","Fagaceae"
"QUCA","","Quercus ×caduca Trel. [incana × nigra]","hybrid oak","Fagaceae"
"QUCO2","","Quercus coccinea Münchh.","scarlet oak","Fagaceae"
"QUCO3","","Quercus ×comptoniae Sarg. [lyrata × virginiana]","Compton oak","Fagaceae"
"QUCOC","","Quercus coccinea Münchh. var. coccinea","scarlet oak","Fagaceae"
"QUCOC","QURI3","Quercus ×richteri Baenitz","","Fagaceae"
"QUCR","","Quercus ×cravenensis Little [incana × marilandica]","Craven oak","Fagaceae"

My feeling is that we do not bring any hybrids, varieties, or subspecies.

Megachile commented 3 years ago

Thinking about this more, I'm not even sure we should be planning to handle hybrids and subspecies the same way we handle host species in the first place, as independent entries. For instance, if I find a hybrid oak, I'm not convinced that the tool will be very useful if I search the hybrid itself, since it will only show results that have been specifically reported on that hybrid (if we've even bothered, which I think we usually haven't). What I really want the tool to do is to simply combine the lists of the hybrid parents.

For subspecies, users will not usually bother adding host associations for species and subspecies, so when you search the subspecies you'll likely only get galls that are specific to one subspecies and not found on the others. I don't know how to handle that necessarily? I'm envisioning a tiered display of results that shows the ones specific to the subspecies and then below that the ones found on the species in general, but idk if that's ideal.

I'm not sure if either of these questions have any bearing on how to handle the range stuff (which as we discussed privately, should ideally be added on a case-by-case basis with a tool that lets users manually import range data for just one at a time) but it seems like it might be worth considering now.

jeffdc commented 3 years ago

Sigh... The data for Minnesota is messed up and truncates before the end. So it will be incomplete

https://plants.sc.egov.usda.gov/csvdownload?plantLst=NRCSStateList&nrcsstate=Minnesota

The data for Idaho has some bad data in it that I had to manually fix.

jeffdc commented 3 years ago

Finally got it all imported into a new DB as we discussed:

jeffdc commented 3 years ago

The following are species in our DB that do not seem to occur in the USDA list. These will not end up with any range info since they are not matched to a plant in the USDA set. I know that a lot of these are some kind of name aliasing issues but the USDA dataset does not have aliases so there is no way to automate matching. If we want to match these we will have to do so manually either by me adding the manual mappings as part of the import code or us doing it by hand after the fact via the upcoming ability to lookup ranges from the dataset. In these cases we would need to make sure that the lookup tool allows non exact matches. @Megachile

7 - Acer heldreichii
19 - Acer x freemanii
21 - Achillea ptamica
30 - Alnus pubescens
37 - Aloe spinosissima
38 - Aloe striata
39 - Aloe nobilis
43 - Ambrosia deltoides
48 - Amelanchier ovalis
49 - Amelanchier vulgaris
55 - Aronia rotundifolia
60 - Artemisia eriantha
72 - Betula albosinensis
74 - Betula americana
75 - Betula concinna
77 - Betula coriacea
78 - Betula humilis
84 - Betula odorata
91 - Buxus koreana
92 - Buxus microphylla
94 - Buxus wallichiana
115 - Corylus columa
117 - Corylus maxima
118 - Corylus tubulosa
119 - Cotoneaster integerrimus
120 - Cotoneaster nebrodensis
121 - Cotoneaster nummularia
122 - Cotoneaster racemiflorus
128 - Crataegus nigra
131 - Crataegus rhipidophylla
132 - Crataegus tomentosa
152 - Fraxinus angustifolia
162 - Geranium multiflorum
163 - Geranium palustre
167 - Geranium sylvaticum
168 - Geranium villosum
171 - Guazuma ulmifolia
174 - Haworthia retusa
177 - Hippophae rhamnoides
179 - Ilex dubia
182 - Ilex serrata
202 - Lycium afrum
204 - Lycium arabicum
209 - Lycium europaeum
210 - Lycium intricatum
212 - Lycium mediterraneum
214 - Lycium ruthenicum
215 - Lycium shawii
220 - Malus x domestica
222 - Mespilus coccinea
223 - Mespilus germanica
259 - Prunus divaricata
264 - Prunus granatum
270 - Prunus mume
275 - Prunus prostrata
276 - Prunus pseudocerasus
277 - Prunus ramburei
278 - Prunus salicina
285 - Prunus yedoensis
289 - Pyrus aria
292 - Pyrus salicifolia
293 - Pyrus spinosa
294 - Pyrus ussuriensis
300 - Quercus sinuata breviloba
304 - Quercus coccifera
312 - Quercus glauca
318 - Quercus ilicis
321 - Quercus ithaburensis
328 - Quercus macrolepis
341 - Quercus pubescens
359 - Rhododendron menziesii
371 - Rubus fruticosus
376 - Rubus thyrsanthus
379 - Ruellia patula
382 - Salix aegyptica
384 - Salix amygdalina
386 - Salix appendiculata
394 - Salix daphnoides
396 - Salix eleagnos
401 - Salix grandifolia
407 - Salix integra
409 - Salix koreensis
412 - Salix lapponica
413 - Salix lapponum
417 - Salix myrsinifolia
419 - Salix myrsinitis
422 - Salix nigricans
430 - Salix retusa
431 - Salix rosmarinifolia
435 - Salix triandra
437 - Salix viridis
444 - Sandoricum koetjape
471 - Sorbus aria
474 - Sorbus commixta
475 - Sorbus pohuashanensis
477 - Sorbus torminalis
482 - Tanacetum abrotanifolium
499 - Ulmus laevis
509 - Vaccinium pennsylvanicum
517 - Viburnum rafinesquianum
652 - Juniperus oxycedrus
653 - Juniperus thurifera
680 - Annona muricata
686 - Litchi sinensis
687 - Litchi chinensis
691 - Gossypium barbadensis
722 - Carya palmeri
791 - Quercus welshii
794 - Quercus petraea
804 - Quercus aliena
1000 - Forsythia xintermedia
1102 - Terminalia buceras
1184 - Fagus crenata
1216 - Quercus phillyreoides
1268 - Hesperocyparis pygmaea
1391 - Lactuca elongata
1393 - Nabalus alba
1446 - Rhaponticum repens
1450 - Pilosella officinarum
1453 - Rubus nutkanus
1458 - Tridophyllum norvegicum
1477 - Rosa cinnamoea
1616 - Smallanthus uvedalia
1620 - Helianthus decepetalus
1759 - Platanus xacerifolia
1829 - Pilosella floribunda
1852 - Salvia melllifera
1894 - Geonoma cuneata
1934 - Salvia californica
1940 - Curatella americana
1941 - Helicteres mexicana
1963 - Acer negundo californicum
2020 - Quercus microphylla
2037 - Enterolobium cyclocarpum
2042 - Quercus bumelioides
2059 - Quercus salicifolia
2068 - Quercus acutifolia
2071 - Quercus costaricensis
2073 - Elaphoglossum moranii
2075 - Pseudolmedia mollis
2077 - Ficus colubrinae
2079 - Ficus obtusifolia
2080 - Lonchocarpus oliganthus
2082 - Quercus zempoaltepecana
2085 - Quercus sapotifolia
2106 - Salix x smithiana
2116 - Koanophyllon albicaule
2230 - Thuja pilcata
2236 - Cupressus pigmaea
2353 - Quercus frutex
2355 - Quercus magnoliifolia
2361 - Quercus laeta
2364 - Quercus eduardi
2366 - Quercus crassipes
2368 - Quercus candicans
2369 - Quercus crassifolia
2491 - Syzygium paniculatum
2492 - Syzygium smithii
2501 - Quercus insignis
2505 - Quercus obtusata
2524 - Quercus chihuahensis
2525 - Quercus resinosa
2619 - Securidaca sylvestris
2631 - Quercus elliptica
2642 - Quercus lancifolia
2656 - Quercus laurina
2661 - Quercus benthamii
2662 - Quercus potosina
Megachile commented 3 years ago

Doing a little spot checking here, a few of these are alias issues--Acer x freemanii appears but is listed as Acer ×freemanii--but most of these are simply not found in the US. I think the solution to this is pretty straightforward; we just match the ones we can match and then use a list like this one (is it possible to build a page that will display a list of "hosts with no range data" like this on an ongoing basis?) to manually fill in the ones in Mexico, Central America, Europe, etc.

Not sure what we want to do about Europe-exclusive hosts of Holarctic inducers--my impulse was to be inclusive because that way we're already prepared for the possibility that a European plant could show up as an ornamental and have that gall etc. But it does put a lot of these rangeless hosts into the db. Thoughts?

If we have a lookup tool we can use that to fill in the cases where aliasing is the issue. I don't think you need to do anything about it either way--users can figure out the correct alias and chance the host name on our end to match and make the lookup work (and change back if needed though in most cases we probably want to follow USDA nomenclature anyway).

jeffdc commented 3 years ago

Here is the new ID screen with Places: Screen Shot 2021-07-26 at 1 03 04 PM

And the Host screen: Screen Shot 2021-07-26 at 1 05 25 PM

The new Place screen: Screen Shot 2021-07-26 at 2 16 42 PM

I have the code all written to import from the USDA CSVs into a new plants db and then ti export place data into the main gallformers db. It all seems to work well. It handles hybrids on import now.

My plan is to get this polished up and deploy it. Then I will work on some Place Admin capabilities. I will write up a new issue to track that work.

Megachile commented 3 years ago

Looks great to me! Awesome work!