Tuesday, February 25, 2020

From Sphinx to DocFX - Generating Python API Documentation with DocFx

Overview


In a previous post Sphinx Quickstart, we covered a very basic setup of Sphinx. In this post, we go farther and talk about Sphinx DocFX YAML, an exporter for the Sphinx Autodoc module. Our goal is to produce YAML files that can be consumed by DocFX, a documentation generator for .NET that also converts YAML files to HTML. Many doc sets at https://docs.microsoft.com/ are generated with DocFX, including Python doc sets that use Sphinx to generate YAML, which is then converted to HTML with DocFX.

Terminology


To understand how to go from Sphinx to DocFX using the Sphinx DocFX YAML exporter, we need to break down some of the terms used...or at least we did to make sense of it all.

Sphinx

  • Sphinx is a documentation generator, it was originally created for Python documentation, but can be used for a range of languages.
  • Sphinx uses reStructuredText (rST) as its markup language. Sphinx's utility comes from the power and straightforwardness of reStructuredText (reST) and its parsing and translating suite, Docutils. reST is used both in .rst files and in docstrings in .py files.
  • In the Quickstart, we created an example reSt file (foo.rst) and built HTML documentation from it. 
  • Autodoc is an extension for Sphinx. (Sphinx is extensible to support the needs of different projects. An extension is simply a Python module.)
  • Autodoc adds directives like "autofunction" and "automodule". These directives determine what API is used to generate docs.
  • When using the autodoc extension (added in the conf.py file) with Sphinx, you are including documentation from Python docstrings. A Python docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. Such a docstring becomes the __doc__ special attribute of that object.
  • When you run the command sphinx-build (or make html if it was created), Sphinx autodoc generates the API documentation for your Python project code using the index.rst (this is the default name, but it can be any name you want). Sphinx imports the code via standard Python import mechanisms, and then generates the proper reST in the Sphinx Python domain. The reST files are then parsed to create doctree files used internally in Sphinx to generate HTML. If you only want the HTML output from Sphinx (and not DocFX), then you can stop here. This is the point at which the post Sphinx Quickstart stops.

sphinx-build

  • Usage: sphinx-build [options] <sourcedir> <outdir> [filenames...]
  • (If you ran sphinx-quickstart, you had the option of creating a make file so that you can just type make html instead of sphinx-build.)
  • This command creates documentation from files in <sourcedir>and places HTML in <outputdir>.
  • This command command looks for <sourcedir>/conf.py for configuration settings.
  • This command creates documentation in different formats. A format can be specified on the command line, otherwise it defaults to HTML. (Check the conf.py file if in doubt.)
  • By default, everything that is outdated is built. Output only for selected files can be built by specifying individual filenames.
  • Since Sphinx has to read and parse all source files before it can write an output file, the parsed source files are cached as “doctree pickles”. Normally, these files are put in a directory called .doctrees under the build directory.
  • If you didn't run the Sphinx Quickstart and don't have an index.rst file to start with, then you could use the sphinx-apidoc command to create module .rst files that would be equivalent to index.rst.

Sphinx DocFx YAML

  • Sphinx DocFX YAML is an exporter for the Sphinx Autodoc module that produces YAML files adhering to the DocFX YAML metadata specification. For more information, see readthedocs.
  • DocFX YAML describes language metadata for programming languages. The main user scenario for language metadata is to generate reference documentation. Specifically, we can use the YAML as input to DocFX and let DocFX generate HTML.
  • YAML files represent the API documentation. Example.
  • DocFX stands for Document Frameworks. To use it, add the extension to the source\conf.py file like so:

    extensions = ['sphinx.ext.autodoc', 'docfx_yaml.extension']
  • With exporter added to conf.py, use Sphinx DocFx as usual by running the command make html.
DocFX

  • DocFX generates API reference documentation from triple-slash comments in C#\VB  source code. Or, it can consume YAML files and render them as HTML.
  • It also allows you to use Markdown files to create additional topics such as tutorials and how-tos, and to customize the generated reference documentation.
  • The punchline is this: From a Python project using Autodoc and SphinxDocFX YAML exporter, you can generate YML files to be used with DocFX. This is what the example below does.
  • Why? Because HTML generated from DocFX has a number of benefits beyond the HTML generated from Sphinx, including API cross referencing, generating from markdown files (.md) alongside API reference, customizable themes and templates.  

An Example


Prerequisites:


Step 1: Clone the travelmarx-blog repo and start in the sphinx-docfx-example directory.

sphinx-docfx-example folder is the root folder. in subsequent steps. You should have the following:
.
└───mycode
    ├───core_api
    │   ├───package1
    │   └───package2
    └───test_api

Step 2: Create config.py and index.rst files.

See the Sphinx Quickstart for information about running the sphinx-quickstart command. Your folder structure should look like this.
.
├───build
├───mycode
│   ├───core_api
│   │   ├───package1
│   │   └───package2
│   └───test_api
└───source
    ├───_static
    └───_templates

Step 3: Edit source\config.py.

Configure the extensions:
extensions = ['sphinx.ext.autodoc', 'docfx_yaml.extension']
Point to the code folder:
import os
import sys
sys.path.insert(0, os.path.abspath('../mycode'))
Some of these lines in the config.py file may already exist and you'll have to uncomment them.

Step 4: Run sphinx-apidoc to create .rst (reStructuredText) files describing the code.

Starting in the sphinx-docfx-example (root) folder, run:
sphinx-apidoc -o source .\mycode
This creates .rst files in the \source folder.

Step 5: Modify the source\index.rst to include modules to document.

Running sphinx-apidoc will produce a source\modules.rst file by default. The modules.rst file is the entry point for documenting the code in \mycode.

source\index.rst (snippet, add the part in red)

Test documentation
=======================
.. toctree::
    :maxdepth: 4
    :caption: Table of Contents
 
    modules

Step 6: Run sphinx-build to create Sphinx's HTML.
sphinx-build source build
Besides building the Sphinx HTML (which you may not care about), this also creates .yml files in the \build\docfx_yaml folder. These will be used in a later step with DocFx.

To view the Sphinx HTML, starting in the root folder, run:
build\index.html
For comparison with docFx HTML (which is generated in Step 7), here is the Sphinx-generated HTML:



Step 7: Confirm that YAML files were generated.

Starting in root folder, run:
dir build\docfx_yaml
You should see a listing of .yml files like "core_api.package1.someclass.SomeClass.yml".

Step 8: Generate an initial docfx.json file.

Starting in the root folder, run:
docfx init -q
This will create a docfx_project folder with the docfx.json configuration file.

Step 9: Copy the Sphinx YAML files to the \docfx_project folder.

Copy .\build\docfx_yaml\* to .\docfx_project\api\*

Step 10: Build the DocFx HTML and serve the docs.

Starting in docfxtest folder, run:
docfx docfx_project\docfx.json --serve

Step 11: View the HTML docs produced by DocFx.

Go to http://localhost:8080.



Some points to note:

  • The difference in the look between Sphinx HTML and DocFx HTML. Both can be customized as needed.
  • How the link to "AnotherClass" is an active link in the DocFX screenshot. This is one of the benefits of using DocFx, cross reference linking.
  • We didn't add any "Articles" (.md files) but that is also a nice feature of DocFx, to integrate API and conceptual (articles) docs. For example of how that could be done, see our Scrapbook101core site.
  • On subsequent runs through the steps above (say, if you changed a docstring in the code), you will typically:
    • delete content in \build folder
    • run steps 6, 9, and 10.

Next Steps:

  • Customize docfx.json file.
  • Read up on cross-linking with DocFx.
  • Add other markdown files (.md) along with API docs.



Monday, February 24, 2020

Sphinx Quickstart


Generate files


The instructions here are for Windows. With slight modifications, they can be applied to other platforms. The code for this post is at https://github.com/travelmarx/travelmarx-blog/tree/master/sphinx-quickstart.

Make sure you have Sphinx installed, then clone the travelmarx-blog repo to your local environment. Starting in the sphinx-quickstart directory you should have the following:

> tree
│   .gitignore

└───mycode
        myclasses.py
        __init__.py

Run the Sphinx quickstart command.

> sphinx-quickstart

Accept defaults for everything except these parameters.
  • Separate source and build directories (y/n) [n]: Y
  • Project name: MyTestDocs
  • Author name(s): your-alias
  • autodoc: automatically insert docstrings from modules: (y/n) [n]: Y 
The last setting for configuring autodoc is important. When answering the quickstart questions, it can be easy to accept the default for this setting which is not to install it. The autodoc extension is configured in the source\conf.py file like so:

extensions = ['sphinx.ext.autodoc']

Build the HTML. The command make html is a convenience for running the command sphinx-build -b html sourcedir buildir. The make file assumes current directory is source directory, and it creates the build directory "build". HTML is the default doc type produced.

> make html
> tree

> tree
├───build
│   ├───doctrees
│   └───html
│       ├───_sources
│       └───_static

├───mycode
└───source
    ├───_static
    └───_templates

Open the docs.

> build\html\index.html

At this point you have basically a framework to build on, but not much else. The index.html page should look like this.


The index.rst file


In the sphinx-quickstart\source folder there should be an index.rst file. Edit the file to add the automodule to automatically document members of a module myclasses.py.

> type index.rst
.. MyTestDocs documentation master file, created by
   sphinx-quickstart on Thu Jun 20 14:06:30 2019.
   Adapt this file to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to MyTestDocs's documentation!
======================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

.. automodule:: myclasses
   :members:

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

The index file is the initial documentation file. You can see that lines in the index.rst appear in the index.html shown above. The index.rst file can contain reStructuredText documentation and directives (the same that appear in Python docstrings). In the example above, we are using automodule to indicate that the docstrings in myclasses should be documented.

Add test Python code


If you cloned the repo, you should have the following:

  • mycode\myclasses.py module.
  • mycode\__init__.py file, which signals that the directory contains a package.


Edit the source\config.py to so that Sphinx can find the code. Here are the lines:

import os
import sys
sys.path.insert(0, os.path.abspath('../mycode'))

Make sure the import lines are not commented out, i.e., have a "#" in front of them.

Here are the two files __init__.py and myclasses.py.

mycode\__init__.py
import myclasses

mycode\myclasses.py
class SimpleClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

class Person:
    """Creates a Person based on name and age."""
    def __init__(self, name, age):
        self.name = name
        self.age = age


Back in the root folder of sphinx-quickstart, rebuild:

> make html

The output should look something like this, which includes docstrings in myclasses.py:


If your code folder is outside the "doctest" folder, make changes to the os.path.abspath in the conf.py file as appropriate.

Your final directory structure should look like this:

>tree
├───build
│   ├───doctrees
│   └───html
│       ├───_sources
│       └───_static
├───mycode
│   └───__pycache__
└───source
    ├───_static
    └───_templates


reStructuredText


Let's add a little more functionality to this quickstart. Suppose we have a file foo.rst that contains documentation we want to include as well. Then we can add foo.rst and make sure it is documented by adding a reference to foo in index.rst:

source\foo.rst

foo module
==========

This is the foo module description.

.. note::

   This is a note.

source\index.rst  (changed part in red)

.. toctree::
   :maxdepth: 2
   :caption: Contents:

   foo

.. automodule:: myclasses
   :members:

The syntax you can use inside of foo.rst is described in Sphinx reStructuredText. At this point in our quickstart, we have HTML generated documentation with some content coming from reStructuredText in an .rst file and some content coming from reStructuredText in docstrings in .py files.

Build the docs again:

> make html

Notice that "foo" appears in doc contents.

If interested, go to the next post in the series: From Sphinx to DocFX - Generating Python API Documentation with DocFx.

Tuesday, December 31, 2019

One Hundred (and More) Common Italian Nouns Derived from Verbs : Confusion Over Masculine and Feminine



The Argument


In the Italian language, nouns can derive from verbs. Verbs can derive from nouns. Also, nouns can derive from adjectives and vice-versa, and much more. It’s a circus of possible conversions. But in this circus, we’d like to call out one specific category because it’s a place we trip up a lot, and that category contains nouns that resemble the first or third-person singular conjugation of a related verb in present indicative.


For example, there is the noun il disprezzo (contempt) and the related verb disprezzare (to despise or scorn). The first-person conjugation of the verb is io disprezzo. Now consider, the noun la sfida (challenge) and the related verb sfidare (to challenge). In this case, the related noun is feminine. The third-person conjugation is lui/lei sfida. This is where we trip up: remembering if the associated noun is masculine or feminine.


We say “related” verb because we aren't sure if the verb came first or the noun. When looking up these nouns in WordReference, the related verb is indicated, but the true etymology is not clear. Spot checking a few noun/verb combinations using Treccani definitions reveals that it's not a simple as saying these nouns derive from the related verbs as it could easily be the other way around, case in point: pranzare from pranzo. The derivations of the words are complicated and better left to linguists. That said, the main point of this post remains valid: there can be confusion between a noun and its related verb, and in particular knowing the gender of the noun.

In the list below, you’ll notice that all the verbs are -ARE verbs. The noun is formed by removing the -ARE and adding the letter O or A. Verbs ending in -ERE and -IRE and their related nouns derive from the past participle usually. For example, la discesa from discendere and la promessa from promettere. We are not talking about these nouns here; we are concerned only with the -ARE verbs.

In English, do we have nouns derived from verbs? Yes we do, and they are called verbal nouns, and they are mostly related to gerunds. There are also nouns created by adding to verbs. See for example, Forming Agent Nouns from Verbs. But these cases in English are not like the Italian cases discussed here where we remove part of verb root and add the letter O or A to form a noun that looks like a conjugation.

From the Treccani reference on conversion, we can get a clue to how to resolve to problem of the ending and knowing if it is O or A. The reference says (paraphrasing) that the major part of the nouns derived from verbs are masculine (end in O). And furthermore, they are usually action verbs and end in -ARE. Many them are verbs ending in -EGGIARE. Here’s the text from the reference:


“A partire da verbi si formano principalmente nomi. La conversione è segnalata da un cambio di classe flessiva (es. arrivare -> arrivo, parcheggiare -> parcheggio, ricoverare -> ricovero). Il maggior numero di nomi è costituito da maschili in -o, i quali di norma sono nomi di azione (-> azione, nomi di) e le regolari estensioni semantiche tipiche di questa classe (risultato dell’azione: disegno, taglio; strumento: cambio; luogo: incrocio). I verbi appartengono quasi esclusivamente alla coniugazione in -are; fra quelli derivati prevalgono quelli con il suffisso -eggiare (conteggiare -> conteggio, palleggiare -> palleggio, pareggiare -> pareggio).”

Of course, we wondered what percentage are masculine. What are our odds of being correct if we guess masculine? To find out, we created a list and counted. The list is composed of words that we encounter daily, so it isn’t in necessarily in any particular order. It would be useful to try find the most frequently used nouns in this category (-ARE verbs with related noun), but we did not do that here.


Of the 100+ nouns (149 to be precise) and their related -ARE verbs in the list below, 39 are feminine (17%) and 110 (83%) are masculine. So, our advice is to guess masculine when in doubt.


There are exceptions to our simplified argument; here are a few that we noted:

  • il pari => parare - masculine noun ending in I.
  • il sistema => sistemare and il programma => programmare - masculine nouns but ending in A.

These exceptions are not included in the list below.

If both a masculine and feminine noun derive from the verb (or seem to - never can be sure as noted above), then both nouns are included in the list below. Examples are la scherma/lo schermo => schermare and il trombo/la tromba => trombare.

Finally, getting back to our circus of possible conversions, the site Valico.org site has a table of morphemes that gives an idea of how nouns are derived from verbs (nomi deverbali), adjectives derive from verbs (aggettivi deverbali), adjectives derive from nouns (aggettivi denominali), verbs derive from nouns (verbi denominali), nouns derive from other nouns (nomi denominali), verbs derive from adjectives (verbi deaggettivali), nouns derive from adjectives (nomi deaggettivali), and adverbs derive from adjectives.

The List


noun => verb  (blue is feminine)

l'abbraccio => abbracciare
l'accumulo => accumulare
l'annucio => annuciare
l'arringa => arringare
l'arrivo => arrivare
l'assaggio => assaggiare
l'attacco => attaccare
l'avvio => avviare
la bada => badare
il bacio => baciare
il ballo => ballare
il balzo => balzare
il beccheggio => beccheggiare
il bisogno => bisognare
il bisticcio => bisticciare
il blocco => bloccare
la caccia => cacciare
il calcio => calciare
il calcolo => calcolare
il cambio => cambiare
il cammino => camminare
il cancello => cancellare
il carico => caricare
la carrucola => carrucolare
la consegna => consegnare
il conteggio => conteggiare
la conquista => conquistare
il continuo => continuare
la copia => copiare
il costo => costare
la cura => curare
la denucia => denuciare
il deposito => depositare
il decreto => decretare
il disegno => disegnare
il disprezzo => disprezzare
il dondolo => dondolare
il dono => donare
la fatica => faticare
la fattura => fatturare
il fermo => fermare
la firma => firmare
la folla => follare
il fracasso => fracassare
il freddo => freddare
la frusta => frustare
la fuga => fugare
la fustella => fustellare
il galoppo => galoppare
il ghiaccio => ghiacciare
il girovago => girovagare
il guardo => guadare
l'impegno => impegnare
l'inchino => inchinare
l'incrocio => incrociare
l'inganno => ingannare
l'ingorgo => ingorare
l'inzio => inziare
il lancio => lanciare
la macchia => macchiare
la maschera => mascherare
la molla => mollare
la nota => notare
il nuoto => nutoare
l'obbligo =>obbligare
l'ombra => ombrare
l'ostacolo => ostacolare
il palleggio => palleggiare
il parcheggio => parcheggiare
il pareggio => pareggiare
il parto => partire
il pascolo => pascolare
il passeggio => passeggiare
il passo => passare
il pasticcio => pasticciare
la pausa => pausare

il pellegrino => pellegrinare
il pericolo => pericolare
il poggio => poggiare
il pranzo => pranzare
la prova => provare
il pugno => pugnare
il quadro => quadrare
il rammarico => rammaricare
il rampollo => rampollare
il raggio => raggiare
il registro => registrare
la ricerca => ricercare
il ricovero => ricoverare
il rientro => rientrare
il rimbalzo => rimbalzare
il rischio => rischiare
il risparmio => risparmiare
il rispetto => rispettare
il ritorno => ritornare
il rombo => rombare
il saldo => saldare
il salto => saltare
lo sbadiglio => sbadigliare
la scherma => schermare
lo schermo => schermare
lo scherzo => scherzare
lo schiaffo => schiaffare
la scopa => scopare
lo scopo => scopare
lo scoppio => scoppiare 
la scoreggia => scoreggiare
la scorta => scortare
lo sdegno => sdegnare
la sfida => sfidare
lo sfoggio => sfoggiare
lo sforzo => sforzare
la slitta => slittare
il soggiorno => soggiornare
il sogno => sognare
la sosta => stostare
lo sparo => sparare
la spesa => spesare
lo spiazzo => spiazzare
la stiva => stivare
lo straccio => stracciare
lo strappo => strappare
lo strumento => strumentare
la sveglia => svegliare
la taccia => tacciare
il taglio => tagliare
la taglia => tagliare

il tappo => tappare
il tarlo => tarlare
la tassa => tassare
il tasto => tastare
il telefono => telefonare
il timbro => timbrare
il tocco => toccare
il tonfo => tonfare
la traccia => tracciare
il tratto => trattare
il trapano => trapanare
il trasloco => traslocare
il trombo => trombare
la tromba => trombare

il trucco => truccare
il tuono => tuonare
il valico => valicare
il vincolo => vincolare
l'urlo => urlare
il volo => volare

References

[1] Treccani - nomi-deverbali
[2] Treccani - conversione
[3] https://en.wikipedia.org/wiki/Verbal_noun
[4] http://www.valico.org/lista_morfemi.pdf

Sunday, August 25, 2019

A Hike to Rifugio Benigni


View from trail 108 looking sourtheast over Val Salmurano.A goat on the way down from Rifugio Benigni.
On trail 108 near Passo Salmurano, heading toward the canalone.Gentianella sp. common on the trail late summer.
Upper left: View from trail 108 looking sourtheast over Val Salmurano.
Upper right: A goat on the way down from Rifugio Benigni.
Lower left: On trail 108 near Passo Salmurano, heading toward the canalone.
Lower right: Gentianella sp. common on the trail late summer.

Overview


Length
: 12 km (7.5 mi)
Duration: 6 hours (Includes ~1 hour for lunch at Rifugio Benigni.)
Elevation: 1330 m (4364 ft) gain. High point at Cima Piazzotti at 2349 m (7707 ft)
Location: Cusio, Alta Val Brembana, Bergamo, Lombardy, Italy

Hike Details


This was one of those hikes hatched over a Saturday morning coffee and hiked the next day, early on Sunday morning. That’s why we love Bergamo! The hike is described on the Club Alpino Italiano (CAI) Bergamo site as Sentiero 108. From Bergamo, you drive up Valle Brembana, forking left in the upper valley toward Olmo al Brembo, Santa Brigida, and finally reaching the little and very steep town of Cusio.

As you wind your way up through Cusio, you reach a point where you pay to use the road. Heading up hill there will be a little ticket machine on your right. We don’t remember the exact location, but you’ll know it when you see it. It costs 2 euros at time of writing this. After paying for a “ticket” you keep driving until you end up in a località called Sciocc at 1508 m where you can park near the trail head.

The first major thing you’ll see on the hike besides the beautiful scenery is the Casera Valletto at 1782 m. This is where we bought cheese and butter on the way down. See attached photo. wordreference.com translates casera as the bizarre but intriguing “cheese hut”. Treccani gives a more satisfying answer: a place in the mountains where dairy products are made from the milk produced during the summer by cattle grazing in the alpine pastures.

Buying cheese and butter at Casera Valletto.Hiking with goats along trail 108 to Rifugio Benigni.Near start of hike on trail 108 - crossing a stream in Val Salmurano.
Left: Buying cheese and butter at Casera Valletto. Center: Hiking with goats along trail 108 to Rifugio Benigni. Right: Near start of hike on trail 108 - crossing a stream in Val Salmurano.

After the Casera, keep following trail 108 and then switch to 107 if you want to avoid Passo Salmurano (2017 m). We took a swing by Passo Slmurano to catch our first glimpse to the north of the Western Rhaetian Alps (Alpi Retiche occidentali), a mountain range in the central part of the Alps. From the pass, we shot west and hit the part of the sentiero 108 generally referred to as a canalone. This was the trickiest part of the trail. Again, our friend wordreference.com translates canalone as the scary “avalanche shoot”. Treccani gives a more nuanced definition: an eroded, narrow furrow typically inclined; a particular type of canalone is one that feeds alpine glaciers. The canalone on sentisenero 108 doesn’t have anything to do with glaciers. It is steep and there was water running through it.

Climbing the canalone on trail 108.A view of Rifugio Benigni.Heading up to Passo Salmurano.
Left: Climbing the canalone on trail 108. Center: A view of Rifugio Benigni. Right: Heading up to Passo Salmurano.

After the canalone and a bit more scrambling here and there, you suddenly emerge on a flat spot at 2222 m where Rifugio Benigni sits at the head of Valle di Salmurano. The rifugio was inaugurated in 1984 with help from the Benigni family who intended to honor the memory of Cesare Benigni who died in 1981 on the nearby Pizzo del Diavolo di Tenda. From the rifugio you can look south upon the Alpi Orobie (also called the Bergamasque Alps) and north on the Central Alps (Wester Rhaetian Alps).

A fresh baked dessert cooling off on the windowsill at Rifugio Benigni.Another rifugio-made dessert - chocolate and coffee cake.A main dish - piatto unico with polenta, spezzatino, funghi, fromaggio.
Left: A fresh baked dessert cooling off on the windowsill at Rifugio Benigni. Right: Another rifugio-made dessert - chocolate and coffee cake. Right: A main dish - piatto unico with polenta, spezzatino, funghi, fromaggio.

Via Mercatorum


On the way to or from the hike, take a moment (or more) to stop in Averara and see a part of the Via Mercatorum. The Via Mercatorum is a collection of medieval trade routes (think mule and foot paths) that connected Bergamo with the Val Valtelinna to the north.

One of the most beautiful parts of the Via Mercatorum is a porticoed passage in Averara. The modern road now passes parallel and lower so that the Via Mercatorum in Averara looks like a covered sidewalk. The most important businesses and people of the 15th and 16th centuries were present on the porticoed Via Mercatorum of Averara. Today, only frescoes and a few clues remain to suggest it.

The slow decline of the Via Mercatorum started in 1593 and the culprit was Venice. Bergamo had been under the dominion of Venice since 1428 and in the late 1500s, Venice was searching for new trade routes to connect Bergamo with Val Valtellina and beyond to its ally, the canton of Grisons in Switzerland. In 1593, the new route, Via Priula, was finished, named after the podestà of Bergamo, Alvise Priula who ordered its construction. At Olmo al Brembo, just south of Averara, the new route took a turn to the east to Piazzolo and Mezzoldo, therefore bypassing Averara.

View of the porticoed Via Mercatorum in Averara.View of the porticoed Via Mercatorum in Averara.CAI map showing the network of trails and the location of Rifugio Benigni.
Left and center: Views of the porticoed Via Mercatorum in Averara. Right: CAI map showing the network of trails and the location of Rifugio Benigni.

Flora


This hike is definitely all about the Euphrasia and Gentianella - at least by the abundance of these two plants. Euphrasia is a genus of about 450 species of herbaceous flowering plants in the family Orobanchaceae. They are semi-parasitic on grasses and other plants. And lo and behold, we tended to see Euphrasia growing in grass. The common name for Euphrasia is Eyebright referring to the plant's use in treating eye infections. Gentianella is a plant genus in the gentian family (Gentianaceae). We saw many purple type - likely one species. Unfortunately, with both plants, we can only identify down to the genus as we can’t figure out the exact species.

For more on flowers found around Bergamo, especially in the Bergamasque Alps, see our Pinterest page: Bergamasque Prealps Flowers and Plants. And our usual disclaimer: we use the resources listed in the post Resources for Identifying Plants around Bergamo to identify plants shown here. If we had to give ourselves a score for identifications, it would be 90% accurate for species and 95% for genus.

The plants are arranged below as follows:

[Family] Genus species – Common name in English (Common name in Italian)

[Apiaceae] Astrantia minor – Minor Masterwort (Astranzia minore)

[Apiaceae] Astrantia minor – Minor Masterwort

[Asteraceae] Anthemis sp. Aromatic flowering plants in the family Asteraceae, closely related to Chamaemelum, and like that genus, known by the common name chamomile.
   

[Asteraceae] Anthemis sp.

[Asteraceae] Solidago sp. Probably S. virgaurea.

[Asteraceae] Solidago sp.

[Celastraceae] Parnassia palustris - Marsh Grass of Parnassus (Parnassia delle paludi). We encountered lots of wet and seeping areas on this hike, perfect for this plant.

[Celastraceae] Parnassia palustris - Marsh Grass of Parnassus

[Fabaceae] Trifolium alpinum – Mountain Clover (Trifoglio montano)

[Fabaceae] Trifolium alpinum – Mountain Clover

[Gentianaceae] Gentianella sp. – Gentian (Genzianella). Likely, G. campestris. One of the most common plant we saw on this hike beside Euphrasia.

[Gentianaceae] Gentianella sp.[Gentianaceae] Gentianella sp.[Gentianaceae] Gentianella sp.

[Gentianaceae] Gentiana asclepiadea - Willow Gentian (Genziana di Esculapio)

[Gentianaceae] Gentiana asclepiadea - Willow Gentian

[Lamiaceae] Prunella vulgaris – Selfheal (Prunella comune)

[Gentianaceae] Gentiana asclepiadea - Willow Gentian

[Orobanchaceae] Euphrasia sp. – Alpine Eyebright (Eufrasia delle alpi)

[Orobanchaceae] Euphrasia sp. – Alpine Eyebright[Orobanchaceae] Euphrasia sp. – Alpine Eyebright

[Papaveraceae] Pseudofumaria lutea – Yellow Corydalis (Colombina gialla)

[Papaveraceae] Pseudofumaria lutea – Yellow Corydalis

[Ranunculaceae] Aconitum lycoctonum – Wolfsbane (Aconito lupaia)
(no photo)

[Ranunculaceae] Aconitum napellus – Monk’s-Hood (Aconito napello)

[Ranuculaceae] Aconitum napellus – Monk’s-Hood[Ranuculaceae] Aconitum napellus – Monk’s-Hood[Ranuculaceae] Aconitum napellus – Monk’s-Hood


Views from the Trail


Lago Piazzotti - near Rifugio Benigni.View south toward dark forms of Torrione S Giacomo.
Left: Lago Piazzotti - near Rifugio Benigni. Right: View south toward dark forms of Torrione S Giacomo.

Panorama from Cima Piazzotti - view north over Lago Zancone and Lago di Trono.
Panorama from Cima Piazzotti - view north over Lago Zancone and Lago di Trono.

Panorama from near Rifugio Benigni looking south.
Panorama from near Rifugio Benigni looking south.

Saved GPS tracks from Cusio to Rifugio Benigni.Hike profile details.
Left: Saved GPS tracks from Cusio to Rifugio Benigni. Right: Hike profile details.

Signage at Passo Salmurano.
Signage at Passo Salmurano.

Sunday, August 11, 2019

A Hike to Rifugio Tagliaferri via Val di Gleno


A member of the Asteraceae family in the process of sending it's seeds.The Gleno Dam from above.
The village of Vilminore in Val di Scalve.Trail 410 in the Val di Gleno.
Upper left: A member of the Asteraceae family in the process of sending it's seeds. Upper right: The Gleno Dam from above. Lower left: The village of Vilminore in Val di Scalve. Lower right: Trail 410 in the Val di Gleno.

Overview


Length: 22.2 km (13.8 mi)
Duration: 9 hours (Includes 1 hour for lunch at the rifugio.)
Elevation: 2290 m (7510 ft) gain. High point at Passo Belviso at 2518 m (8260 ft)
Location: Pian del Gleno, Vilminore di Scalve, Bergamo, Lombardy, Italy

Hike Details


The main driver for today’s hike was to see the Gleno Dam. Ever since we saw a photo of it several years ago - part of it missing and in an impossible but beautiful looking setting - we knew we would go see it. Add to that the necessity of place to eat (because we walk to eat) and the hike to Rifugio Tagliaferri via Val di Gleno was born.

We were advised not to take Sentiero 411Sentiero 410 (via Val di Gleno) to the Rifugio Tagliaferri but rather to take the more popular Sentiero 413 (via Valle del Vò). We were glad we stuck to our original idea because Sentiero 411 seemed to be the less popular route, which for us was a good thing. And, Sentiero 411 is about the same in time and distance.

The hike worked out like this:

  1. We started in Vilminore and took the shuttle up to Pianezza.
    • If you are off-season, you can try and drive up to Pianezza and park.
    • Or, you can start walking in Vilminore.
  2. From Pianezza, we took Sentiero 411 to the dam.
  3. From the dam, we picked up Sentiero 410 to Passo Belviso.
  4. From Passo Belviso, we picked up Sentiero 321 to Rifugio Tagliaferri.
  5. Lunch at Tagliaferri.
  6. Reverse direction and head back to Pianezza/Vilminore.

Hike stats: distance, velocity, time and altitude.The hike route in the Val di Gleno.
Left: Hike stats: distance, velocity, time and altitude. Right: The hike route in the Val di Gleno.

A note on the shuttle bus:

We started in Vilminore and parked the car in one of the many free lots. From there, we took a small shuttle (navetta) up to Pianezza, where we started hiking. You can also hike right out of Vilminore by walking up to Pianezza following the road or taking one of the trails marked “Diga del Gleno”. We walked back down the road from Pianezza to Vilminore at the end of the day and it wasn’t bad. The shuttle costs 4 euros one way. We purchased tickets at Bar Imperial and the shuttle stop is at the municipio across the street from the bar. Why take a shuttle instead of driving up to Pianezza? During the summer months, only residents are allowed and you must take the shuttle. Off season, and you don’t need to worry. On our way up to the dam – around 8:00 am – it wasn’t crowded at all, that is, no people on the shuttle, few hikers, and few people at the lake except for some overnight campers. When we returned in the afternoon, the tents on the lake where gone and replaced by many families up to enjoy Sunday at the lake. And there was a waiting line for the shuttles back going from Pianezza down to Vilminore, which is why we walked.

On this hike it’s hard to get lost, but in bad weather, uncertainty, or just plain wanting to know how far to go to the next landmark, you can download the GPX tracks from the CAI links included in this post and use them in MAPS.ME. We’ve found that you sometimes need to convert tracks from the CAI Bergamo site from GPX to KML to get them to load in MAPS.ME.

There was a small refreshment stand / bar on the lake. After that, there is nothing until you reach Rifugio Tagliaferri. The Rifugio is named for Nani Tagliaferri, the first president of the Valle di Scalve chapter of CAI. Tagliaferri, the person, disappeared in 1981 in the glaciers of the Peruvian Andes. Tagliaferri, the rifugio, was inaugurated in 1985.

Rifugio Tagliaferri - pasta.Rifugio Tagliaferri - salamella with polenta.Rifugio Tagliaferri - lamb with polenta.Rifugio Tagliaferri - homemade apple cake.
Some of the dishes a Rifugio Tagliaferri. Left to right: a simple pasta dish, salamella with polenta, lamb with polenta, and homemade apple cake.

The Gleno Dam


The central part of the dam collapsed early on the first of December 1923. From 1535 m (5,036 ft), the water rushed out finding its way to the north end of Lago Iseo at approximately 186 m (610 ft) and killing more than 350 people along the way. What went wrong? The dam had just been completed not more than four months before, but there were warning signs along the way from the quality of the cement and reinforcement used to a change in the type of dam permitted and type build. The last point is interesting because the Gleno Dam was permitted as a gravity dam but during construction which was changed from a gravity dam to a multiple-arch dam. A gravity dam relies on its weight to hold back water. A multiple-arch dam uses less concrete and relies on distributing the force of the water to the arches (buttresses) on both sizes of the dam. It’s these arches that give the Gleno Dam its captivating look as if it were of ancient Roman origin. But sadly, it wasn’t or else it would probably still be standing. Cost cutting to save concrete and reused scrap metal from WWI inside the concrete likely led to its collapse.

However, a very thorough analysis (in Italian) Il crollo della Diga di Pian del Gleno: Errore Tecnico? suggests that situation was much more complicated and that the dam was built to specifications of the time. Further, many of the allegations of bad cement or reused scrap metal may not have much to do with the collapse. The analysis also discusses the evidence supporting the possibility of sabotage, including the theft of dynamite two days before the collapse. The court case ran from 1924 to 1927 and found the owners and many others involved guilt, with compensation for damages to the survivors.

View of the Gleno Dam (La Diga del Gleno) which collapsed in 1923.View of the Gleno Dam (La Diga del Gleno) which collapsed in 1923.View of the Gleno Dam (La Diga del Gleno) which collapsed in 1923.View of the Gleno Dam (La Diga del Gleno) which collapsed in 1923.View of the Gleno Dam (La Diga del Gleno) which collapsed in 1923.View of the Gleno Dam (La Diga del Gleno) which collapsed in 1923.
Views of the Gleno Dam (La Diga del Gleno) which collapsed in 1923.


An interesting point raised in the report is that the dam was planned to provide energy for a cotton factory. At one time, the valleys above Bergamo were filled with industry run by the water. Today, as you drive up the valleys, in this case Val Seriana and then into the Val di Scalve, you can’t help but notice along the road (which stays close to the river) the hulking abandoned factories that speak to that past. Some of the structures are beautiful examples of industrial architecture.

Another point from the analysis was this disturbing sentence: “L’ondata fu preannunciata da un violento spostamento d’aria che iniziò l’opera di distruzione, strappando le vesti a chi si trovava all’aperto, seguita dalla massa d’acqua che, dopo aver devastato I centri abitati della valle, si esaurì nell ago d’Iseo.” The translation is this: “The wave was preceded by a violent rush of air before the destruction, ripping off the clothes of those who were outdoors. The rush of air was followed by a mass of water that, after ravaging the population centers of the valley, found its way to the top of Lago Iseo.” The ripping-off of the clothes part stuck in my mind. In the report, there is a picture of the victims laid out in a room - presumably by the responders to the disaster - some with bits of cloth or twigs and branches discretely placed over private parts.

To this day, we’ll never know what caused the dam to collapse.

Information board at the dam talking about the collapse.
Information board at the dam talking about the collapse.


Flora

If we had to pick one plant that characterized this hike, it would be Sanguisorba. It is a genus of flowering plants in the family Rosaceae native to the temperate regions of the Northern Hemisphere. The common name is burnet. We guess we were seeing the most common type S. dodecandra – Italian Burnet (Salvastrella con dodici stami).

For more on flowers found around Bergamo, especially in the Bergamasque Alps, see our Pinterest page: Bergamasque Prealps Flowers and Plants.

Usual disclaimer: we use the resources listed in the post Resources for Identifying Plants around Bergamo to identify plants shown here. If we had to give ourselves a score for identifications, it would be 95% accurate for species and 98% for genus.

The plants are arranged below as follows:

[Family] Genus species – Common name in English (Common name in Italian)

[Amaryllidaceae] Allium schoenoprasum – Wild Chives (Erba cipollina)
[Amaryllidaceae] Allium schoenoprasum – Wild Chives (Erba cipollina)[Amaryllidaceae] Allium schoenoprasum – Wild Chives (Erba cipollina)

[Apiaceae] Bupleurum petraeum – Rock Hare’s Ear (Bupleuro delle rocce)
[Apiaceae] Bupleurum petraeum – Rock Hare’s Ear (Bupleuro delle rocce)[Apiaceae] Bupleurum petraeum – Rock Hare’s Ear (Bupleuro delle rocce)

[Asteraceae] Carlina sp.
[Asteraceae] Carlina sp.

[Asteraceae] Centaurea uniflora - Plume Knapweed (Fiordaliso alpino con un capolino)
[Asteraceae] Centaurea uniflora - Plume Knapweed (Fiordaliso alpino con un capolino)

[Asteraceae] Cirsium erisithales – Yellow Thistle (Cardo zampa d'orso)
[Asteraceae] Cirsium erisithales – Yellow Thistle (Cardo zampa d'orso)

[Asteraceae] Cirsium spinosissimum - Spiniest Thistle (Cardo spinosissimo)
[Asteraceae] Cirsium spinosissimum - Spiniest Thistle (Cardo spinosissimo)

[Asteraceae] Crespis aurea – Golden Hawk's Beard (Radicchiella aranciata)
[Asteraceae] Crespis aurea – Golden Hawk's Beard (Radicchiella aranciata)

[Asteraceae] Leontopodium sp. – Edelweiss (Stella alpina)
[Asteraceae] Leontopodium sp. – Edelweiss (Stella alpina)

[Boraginaceae] Eritrichum nanum – Arctic Alpine Forget-me-Not (Eritrichio nano)
[Boraginaceae] Eritrichum nanum – Arctic Alpine Forget-me-Not (Eritrichio nano)[Boraginaceae] Eritrichum nanum – Arctic Alpine Forget-me-Not (Eritrichio nano)

[Brassicaceae] Noccaea rotundifolium – Round Leaved Penny Cress (Erba storna a foglie rotunda)
[Brassicaceae] Noccaea rotundifolium – Round Leaved Penny Cress (Erba storna a foglie rotunda)

[Caryophyllaceae] Cerastium arvense – Filed Chickweed (Peverina dei campi)
[Caryophyllaceae] Cerastium arvense – Filed Chickweed (Peverina dei campi)[Caryophyllaceae] Cerastium arvense – Filed Chickweed (Peverina dei campi)

[Caryophyllaceae] Dianthus sp.
[Caryophyllaceae] Dianthus sp.

[Caryophyllaceae] Dianthus superbus – Fringed Pink (Garofano superbo)
[Caryophyllaceae] Dianthus superbus – Fringed Pink (Garofano superbo)

[Caryophyllaceae] Saponaria officinalis – Bouncingbet, Common Soapwort (Saponaria comune)
[Caryophyllaceae] Saponaria officinalis – Bouncingbet, Common Soapwort (Saponaria comune)

[Celastraceae] Parnassia palustris - Marsh Grass of Parnassus (Parnassia delle paludi)
[Celastraceae] Parnassia palustris - Marsh Grass of Parnassus (Parnassia delle paludi)

[Crassulaceae] Rhodiola rosea – Roseroot Stonecrop (Rodiola rosea)
[Crassulaceae] Rhodiola rosea – Roseroot Stonecrop (Rodiola rosea)[Crassulaceae] Rhodiola rosea – Roseroot Stonecrop (Rodiola rosea)

[Crassulaceae] Sempervivium sp. – Mountain Houseleek (Semprevivo), possibly S. montanum
[Crassulaceae] Sempervivium sp. – Mountain Houseleek (Semprevivo), possibly S. montanum

[Gentianaceae] Gentian sp. – Gentian (Genziana)
[Gentianaceae] Gentian sp. – Gentian (Genziana)

[Orobanchaceae] Pedicularis sp. – Lousewort (Pediculare) – possibly P. kerneri.
[Orobanchaceae] Pedicularis sp. – Lousewort (Pediculare) – possibly P. kerneri.

[Orobanchaceae] Rhinanthus sp. - Yellow Rattle (Cresta di gallo)
[Orobanchaceae] Rhinanthus sp. - Yellow Rattle (Cresta di gallo)

[Orobanchaceae] Euphrasia sp. – Alpine Eyebright (Eufrasia delle alpi)
[Plantaginaceae] Veronica sp. – Alpine Eyebright (Eufrasia delle alpi)

[Papaveraceae] Pseudofumaria lutea – Yellow Corydalis (Colombina gialla)
[Papaveraceae] Pseudofumaria lutea – Yellow Corydalis (Colombina gialla)

[Plantaginaceae] Linaria alpina – Alpine Toadflax (Linajola alpina)
[Plantaginaceae] Linaria alpina – Alpine Toadflax (Linajola alpina)[Plantaginaceae] Linaria alpina – Alpine Toadflax (Linajola alpina)

[Plumbaginaceae] Armeria alpina – Alpine Thrift (Spillone alpino)
[Plumbaginaceae] Armeria alpina – Alpine Thrift (Spillone alpino)[Plumbaginaceae] Armeria alpina – Alpine Thrift (Spillone alpino)[Plumbaginaceae] Armeria alpina – Alpine Thrift (Spillone alpino)

[Rosaceae] Potentilla nitida – Pink cinquefoil (Cinquefoglia delle Dolomiti)
[Rosaceae] Potentilla nitida – Pink cinquefoil (Cinquefoglia delle Dolomiti)

[Rosaceae] Sanguisorba dodecandra – Italian Burnet (Salvastrella con dodici stami)
[Rosaceae] Sanguisorba dodecandra – Italian Burnet (Salvastrella con dodici stami)

[Ranunculaceae] Pulsatilla alpina – Alpine Pasqueflower (Pulsatilla alpina)
[Ranunculaceae] Pulsatilla alpina – Alpine Pasqueflower (Pulsatilla alpina)[Ranunculaceae] Pulsatilla alpina – Alpine Pasqueflower (Pulsatilla alpina) 

[Saxifragaceae] Saxifraga aizoides – Yellow Saxifrage (Sassifraga gialla)
[Saxifragaceae] Saxifraga aizoides – Yellow Saxifrage (Sassifraga gialla)

[Saxifragaceae] Saxifraga byroides – Mossy Saxifrage (Sassifraga briode)
[Saxifragaceae] Saxifraga byroides – Mossy Saxifrage (Sassifraga briode)[Saxifragaceae] Saxifraga byroides – Mossy Saxifrage (Sassifraga briode)

Miscellaneous Shots of the Hike


Donkeys (or are they mules!?) eye us suspiciously.Donkeys (or are they mules!?) eye us suspiciously.Walking up the Val di Gleno.
Left and center: Donkeys (or are they mules!?) eye us suspiciously. Right: Walking up the Val di Gleno.

The trail along the Gleno River.On Passo Belviso - A view of Lago Belviso.View toward Presolana.
Left: The trail along the Gleno River. Center: On Passo Belviso - A view of Lago Belviso. Right: View toward Presolana.

A mural in Vilminore showing trail to the Gleno Dam.A war monument in Castione della Presolana.Vilminore - Parrocchia S. Maria Assunta e S. Pietro Apostolo.
Left: A mural in Vilminore showing trail to the Gleno Dam. Center: A war monument in Castione della Presolana. Right: Vilminore - Parrocchia S. Maria Assunta e S. Pietro Apostolo.

The start of the trail, just above Pianezza.Trail 411 from Pianezza to the Gleno Dam.Trail near Passo Belviso.
Left: The start of the trail, just above Pianezza. Center: Trail 411 from Pianezza to the Gleno Dam. Right: Trail near Passo Belviso.