Commonly seen Genealogical Reports that are not supported

How hard is it replicate reports in Gramps?

There are a few Historical Societies that have their own standard formats for submitting genealogies for publication or as part of their application for admittance process. Some, like the format used for the “National Genealogical Society Quarterly”, have become de facto standards. It would be convenient to be able to replicate suc a formats.

Likewise, most Lineage Societies have their own format for submitting supporting documentation proving eligibility for membership. Most in USA seem to accept the format used by the “Daughters of the American Revolution

The New England Historic Genealogical Society developed the NGSQ descendant numbering system as part of their report format. That presentation format is used for publishing in the “National Genealogical Society Quarterly” and the “New England Historical and Genealogical Register” Superficially, some resemblance can be created with the Detailed Descendant Book (provided you tweak a bunch of options*)

The TreeAndLeaf.org website has a nice article on the format used in NGS Quarterly.


If anyone has a tool that can download a GEDCOM from FamilySearch, the data above is a earlier version Moses Moss; b. 1 Jul 1701 Lyons, Stafford, England; d.1736. Replicating a report with the same data might be eaiser than starting with unknowns on both sides.

* Text Reports : Detailed Descendant Book
Document options:
Output Format: PDF document
General
Filter: Descendants of
Center Person = Progenitor
Numbering systems: Record/Modified Register: numbering
Content
Use Callname - No
Use full dates - Yes
List Children - Yes
Compute death age - No
Omit duplicate ancestors - Yes
Use complete sentences - No
add descendant references - Yes
Include
Enable none of these options
Include (2)
include spouses - No
Include spouse reference - Yes
Include sign of succession - Yes
Include path to start person - Yes

1 Like

Holy crap! I just asked the ChatGPT to write a Python script and it did! Plus it gave example output and summarized the code in plain (techie) language.

Me:
Create a Python script that takes a 2 dimensional array of text strings (with the array being a list of Given name strings and Surname strings) that prints the Strings in list order with a superscript list item index between each Given name and Surname and semicolons separating each element of the list. Surnames should be in Small Caps format.

It responds:
Certainly! Here’s a Python script that takes a 2-dimensional array of text strings, where each sub-array contains a Given name and Surname, and prints the strings in list order with a superscript list item index between each Given name and Surname, and semicolons separating each element of the list. Surnames are printed in Small Caps format:

def print_name_list(arr):
    for i, name in enumerate(arr):
        given_name, surname = name
        if i == len(arr) - 1:
            print(f"{given_name}{superscript(i)} {small_caps(surname)}")
        else:
            print(f"{given_name}{superscript(i)} {small_caps(surname)}; ", end="")

def superscript(num):
    superscript_chars = str.maketrans("0123456789", "⁰¹²³⁴⁵⁶⁷⁸⁹")
    return str(num).translate(superscript_chars)

def small_caps(text):
    small_caps_chars = str.maketrans("abcdefghijklmnopqrstuvwxyz", "ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘǫʀꜱᴛᴜᴠᴡxʏᴢ")
    return text.translate(small_caps_chars)

# Example usage
arr = [["Alice", "SMITH"], ["Bob", "JONES"], ["Charlie", "JOHNSON"]]
print_name_list(arr)

This will output:
Alice⁰ Sᴍɪᴛʜ; Bob¹ Jᴏɴᴇs; Charlie² Jᴏʜɴsᴏɴ

In this example, print_name_list() takes a 2-dimensional array of text strings (arr) as input, where each sub-array contains a Given name and Surname. For each name in the array, it prints the Given name with a superscript list item index using the superscript() function, followed by the Surname in Small Caps format using the small_caps() function.

The superscript() function is the same as in the previous example, and the small_caps() function takes a string as input and returns a new string where each character is replaced by the corresponding Small Caps character.

The print_name_list() function uses the end parameter in the print() function to print each name and superscript index with a semicolon and space separator ("; "), except for the last element, which is printed without a separator.

I thought, that’s close. But I left off a couple characteristics off the specification:

Me
Create a Python script that takes a 2 dimensional array of text strings (with the array being a list of a Given name strings and Surname strings) that prints the Strings in reverse list order with a superscript list item index between each Given name and Surname and semicolons separating each element of the list. Surnames should be in Small Caps format. If the Surname does not change from the previous list item, omit that Surname, The list item index starts with 1, not 0.

Sure! Here’s a Python script that takes a 2-dimensional array of text strings, where each sub-array contains a Given name and Surname, and prints the strings in reverse list order with a superscript list item index between each Given name and Surname, and semicolons separating each element of the list. Surnames are printed in Small Caps format, and if the Surname does not change from the previous list item, it is omitted. The list item index starts with 1, not 0:

def print_reverse_name_list(arr):
    prev_surname = ""
    for i, name in enumerate(reversed(arr)):
        given_name, surname = name
        if surname != prev_surname:
            if i == 0:
                print(f"{given_name}{superscript(len(arr) - 1)} {small_caps(surname)}")
            else:
                print(f"{given_name}{superscript(len(arr) - i)} {small_caps(surname)}; ", end="")
            prev_surname = surname
        else:
            if i == 0:
                print(f"{given_name}{superscript(len(arr) - 1)}")
            else:
                print(f"{given_name}{superscript(len(arr) - i)}; ", end="")

def superscript(num):
    superscript_chars = str.maketrans("0123456789", "¹²³⁴⁵⁶⁷⁸⁹⁰")
    return str(num + 1).translate(superscript_chars)

def small_caps(text):
    small_caps_chars = str.maketrans("abcdefghijklmnopqrstuvwxyz", "ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘǫʀꜱᴛᴜᴠᴡxʏᴢ")
    return text.translate(small_caps_chars)

# Example usage
arr = [["Alice", "SMITH"], ["Bob", "JONES"], ["Charlie", "JOHNSON"], ["David", "JONES"]]
print_reverse_name_list(arr)

This will output:
David⁴ Jᴏɴᴇs; Charlie³ Jᴏʜɴsᴏɴ; Bob² Jᴏɴᴇs; Alice¹ Sᴍɪᴛʜ

In this example, print_reverse_name_list() takes a 2-dimensional array of text strings (arr) as input, where each sub-array contains a Given name and Surname. It prints each name in the array in reverse order, with the Given name followed by a superscript list item index using the superscript() function, and followed by the Surname in Small Caps format using the small_caps() function, except for Surnames that are the same as the previous item, which are omitted.

The superscript() function is slightly modified from the previous example to start the list item index with 1, and the small_caps() function is the same.

The print_reverse_name_list() function uses a loop over a reversed copy of the input array, and keeps track of the previous Surname using the prev_surname variable. It uses conditional statements to print the appropriate output for each name in the list, either with the Surname or without it if it is the same as the previous name. It also uses the end parameter in the print() function to print each name and superscript index with a semicolon and space

The NEHGR (NGSQ?) style progenitor breadcrumb format (for David Jones, a 4th generation direct descendant of Bob Smith) would look like:
David⁴ Jᴏɴᴇs. (Charlie³ Jᴏɴᴇs, Alice², Bob¹ Sᴍɪᴛʜ)

It will probably be fairly straightforward to create a custom NEHGR report that uses this progenitor breadcrumb format by forking the Detailed Descendant Book report. And then to tweak the Detailed Descendant Book report to have a simple option to support their format.

But let’s say that we wanted to add the progenitor breadcrumb format as an expansion to the relationship calculator so that it could be used any report.

It begs a few questions:

  • how should the hack be inserted in the Relationship Calculator as an experiment?
  • how would the format expansion be submitted for inclusion in Gramps core?
  • can text decorations (bold, small caps, superscript, italics, underscore) be included?
  • how could you include formatting options for Relationship_Calculator function calls?

And say that you wanted to include options. (For instance, the superscript in the example is the generational distance. But the Gramps ID or the ahnentafel number would be useful in other circumstances.)

Here’s an example of another form of breadcrumbs, which are placed in the title of each page of a book. With this form, the crumbs are able to include more detail (in this case, full name, birth and death years, and the page number on which the ancestor first appears), and the names in the body of the page are neatly crumb-free.

image

(Rauenzahner to Routson: a family on the move. Dern, John Philip and M. Marjorie Waidner. Camden, ME: Picton Press, c1993. Page 106.)

I could be wrong, but I think the code for this doesn’t belong in the relationship calculator, but rather in the report. The descendant report (descendreport.py) already includes the classes for various numbering schemes. (Maybe those should be relocated to a place where they are more easily reused by other reports?) At any rate, for purposes of experimentation, I think it would be much easier to hack the report than the relationship calculator.

Yes, that’s a possibility and why I brought it up for discussion.

I see a pedigree breadcrumb as a good candidate for re-use elsewhere. (A breadcrumb that embeds draggable hotlinks would also be useful. See the breadcrumbing that @cdhorn did for Place Title hierarchies in the top cards of CardView. It was inspired by the File location breadcrumbs of the GTK file chooser.)

So the idea of re-use inspires curiosity about how such things are evaluated as being only special purpose feature that belongs in a single report, or general purpose feature that could be importable from a standard module. … and then the workflow for getting the ‘general purpose’ features into the right place.