Skip to content

Flavours

One procedure, shown under every setting the document generator takes, from the smallest useful representation to the one a query is run against. Each section ends with a question, the SPARQL that asks it, and the answer that flavour gives. The answers are computed when this page is built, so a query that stops working stops appearing here as though it still did.

A profile is a name for a set of those settings: which wrappers are transparent, which types go opaque, whether keywords fold, and which lookups run. The ast profile asks for everything below. RDF is not a second derivation of the source; it is the same document in another notation, so the three tabs on the right of each section always say the same thing. The graph draws only the nodes and the arrows between them, since half the triples in any flavour are the corners of a span.

The @context is identical in every flavour and is left out of the JSON tabs, where it would bury the part that differs.

The @context every flavour shares
{
 "@context": {
  "awl": "https://w3id.org/awl/schema/",
  "py": "https://w3id.org/awl/py/",
  "xsd": "http://www.w3.org/2001/XMLSchema#",
  "@vocab": "https://w3id.org/awl/schema/",
  "@base": "https://w3id.org/awl/py/",
  "type": "@type",
  "_type": "@type",
  "literal": {"@id": "awl:literal"},
  "var": {"@id": "awl:var"},
  "span": {"@id": "awl:span"},
  "order": {"@id": "awl:order", "@type": "xsd:integer"},
  "argument_index": {"@id": "awl:argumentIndex", "@type": "xsd:integer"},
  "iteration": {"@id": "awl:iteration", "@type": "xsd:integer"},
  "iteration_count": {"@id": "awl:iterationCount", "@type": "xsd:integer"},
  "event_count": {"@id": "awl:eventCount", "@type": "xsd:integer"},
  "start_line": {"@id": "awl:startLine", "@type": "xsd:integer"},
  "start_col": {"@id": "awl:startCol", "@type": "xsd:integer"},
  "end_line": {"@id": "awl:endLine", "@type": "xsd:integer"},
  "end_col": {"@id": "awl:endCol", "@type": "xsd:integer"},
  "alias_of": {"@id": "awl:aliasOf"},
  "alias_root": {"@id": "awl:aliasRoot"},
  "argument_name": {"@id": "awl:argumentName"},
  "argument_types": {"@id": "awl:argumentTypes"},
  "branch_taken": {"@id": "awl:branchTaken"},
  "declaration_form": {"@id": "awl:declarationForm"},
  "declared_types": {"@id": "awl:declaredTypes"},
  "exported_name": {"@id": "awl:exportedName"},
  "from_module": {"@id": "awl:fromModule"},
  "imported_name": {"@id": "awl:importedName"},
  "in_function": {"@id": "awl:inFunction"},
  "is_alias": {"@id": "awl:isAlias"},
  "is_link": {"@id": "awl:isLink"},
  "is_many": {"@id": "awl:isMany"},
  "is_star": {"@id": "awl:isStar"},
  "keyword_arguments": {"@id": "awl:keywordArguments"},
  "local_name": {"@id": "awl:localName"},
  "member_path": {"@id": "awl:memberPath"},
  "node_type": {"@id": "awl:nodeType"},
  "parser_type_name": {"@id": "awl:parserTypeName"},
  "produced_by": {"@id": "awl:producedBy"},
  "range_name": {"@id": "awl:rangeName"},
  "source_text": {"@id": "awl:sourceText"},
  "value_callee": {"@id": "awl:valueCallee"},
  "value_path": {"@id": "awl:valuePath"},
  "written_by": {"@id": "awl:writtenBy"},
  "member": {"@id": "awl:member", "@type": "@id"},
  "member_of": {"@id": "awl:memberOf", "@type": "@id"},
  "root_type": {"@id": "awl:rootType", "@type": "@id"},
  "range": {"@id": "awl:range", "@type": "@id"},
  "depends_on": {"@id": "awl:dependsOn", "@type": "@id"},
  "refers_to": {"@id": "awl:refersTo", "@type": "@id"},
  "id": {"@id": "awl:id"},
  "next": {"@id": "awl:next", "@type": "@id"},
  "when_true": {"@id": "awl:whenTrue", "@type": "@id"},
  "when_false": {"@id": "awl:whenFalse", "@type": "@id"},
  "each_item": {"@id": "awl:eachItem", "@type": "@id"},
  "exhausted": {"@id": "awl:exhausted", "@type": "@id"},
  "repeat": {"@id": "awl:repeat", "@type": "@id"},
  "on_error": {"@id": "awl:onError", "@type": "@id"},
  "body": {"@id": "awl:body", "@container": "@list"},
  "orelse": {"@id": "awl:orelse", "@container": "@list"},
  "finalbody": {"@id": "awl:finalbody", "@container": "@list"},
  "Method": {"@id": "awl:Method", "@context": {"args": {"@id": "awl:parameter", "@container": "@list"}}},
  "Call": {"@id": "awl:Call", "@context": {"args": {"@id": "awl:argument", "@container": "@list"}}},
  "ChargeParam": {
   "@id": "py:battery.params/ChargeParam",
   "@context": {"@vocab": "https://w3id.org/awl/py/battery.params/ChargeParam#", "target_voltage": {"@type": "xsd:double"}}
  },
  "Report": {"@id": "py:battery.report/Report", "@context": {"@vocab": "https://w3id.org/awl/py/battery.report/Report#"}}
 }
}

One lookup at a time

The tree

The document lookup alone, which is the editor model: statements, calls and literals, with the constructor collapsed into a typed node. The minimal form, and the only one that regenerates the source it came from.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "@type": "Module",
   "body": [
    {"@type": "ImportFrom", "module": "battery.device", "names": ["charge", "measure"], "level": 0, "order": 0},
    {"@type": "ImportFrom", "module": "battery.params", "names": ["ChargeParam"], "level": 0, "order": 1},
    {"@type": "ImportFrom", "module": "battery.report", "names": ["Report"], "level": 0, "order": 2},
    {
     "@type": "FunctionDef",
     "name": "procedure",
     "args": [{"arg": "cycles", "annotation": {"var": "int"}}],
     "body": [
      {"@type": "Assign", "targets": [{"var": "report"}], "value": {"@type": "Call", "func": {"var": "Report"}}, "order": 0},
      {"@type": "Assign", "targets": [{"var": "i"}], "value": {"literal": 0}, "order": 1},
      {
       "@type": "While",
       "test": {"@type": "Compare", "left": {"var": "i"}, "ops": ["Lt"], "comparators": [{"var": "cycles"}]},
       "body": [
        {"@type": "Call", "func": {"var": "charge"}, "args": [{"@type": ["ChargeParam"], "target_voltage": 4.2}], "order": 0},
        {"@type": "AugAssign", "target": {"var": "i"}, "op": "Add", "value": {"literal": 1}, "order": 1}
       ],
       "order": 2
      },
      {
       "@type": "Assign",
       "targets": [{"@type": "Attribute", "value": {"var": "report"}, "attr": "capacity"}],
       "value": {"@type": "Call", "func": {"var": "measure"}},
       "order": 3
      }
     ],
     "returns": {"literal": null},
     "order": 3
    }
   ]
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix ns1: <https://w3id.org/awl/py/battery.params/ChargeParam#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

[] a awl:Module ;
    awl:body ( [ a awl:ImportFrom ;
                awl:level 0 ;
                awl:module "battery.device" ;
                awl:names "charge",
                    "measure" ;
                awl:order 0 ] [ a awl:ImportFrom ;
                awl:level 0 ;
                awl:module "battery.params" ;
                awl:names "ChargeParam" ;
                awl:order 1 ] [ a awl:ImportFrom ;
                awl:level 0 ;
                awl:module "battery.report" ;
                awl:names "Report" ;
                awl:order 2 ] [ a awl:FunctionDef ;
                awl:args [ awl:annotation [ awl:var "int" ] ;
                        awl:arg "cycles" ] ;
                awl:body ( [ a awl:Assign ;
                            awl:order 0 ;
                            awl:targets [ awl:var "report" ] ;
                            awl:value [ a awl:Call ;
                                    awl:func [ awl:var "Report" ] ] ] [ a awl:Assign ;
                            awl:order 1 ;
                            awl:targets [ awl:var "i" ] ;
                            awl:value [ awl:literal 0 ] ] [ a awl:While ;
                            awl:body ( [ a awl:Call ;
                                        awl:argument ( [ a <https://w3id.org/awl/py/battery.params/ChargeParam> ;
                                                    ns1:target_voltage 4.2e+00 ] ) ;
                                        awl:func [ awl:var "charge" ] ;
                                        awl:order 0 ] [ a awl:AugAssign ;
                                        awl:op "Add" ;
                                        awl:order 1 ;
                                        awl:target [ awl:var "i" ] ;
                                        awl:value [ awl:literal 1 ] ] ) ;
                            awl:order 2 ;
                            awl:test [ a awl:Compare ;
                                    awl:comparators [ awl:var "cycles" ] ;
                                    awl:left [ awl:var "i" ] ;
                                    awl:ops "Lt" ] ] [ a awl:Assign ;
                            awl:order 3 ;
                            awl:targets [ a awl:Attribute ;
                                    awl:attr "capacity" ;
                                    awl:value [ awl:var "report" ] ] ;
                            awl:value [ a awl:Call ;
                                    awl:func [ awl:var "measure" ] ] ] ) ;
                awl:name "procedure" ;
                awl:order 3 ;
                awl:returns [ ] ] ) .
graph TD
  n0(["1"])
  n1(["Assign #1"])
  n2(["Call #1"])
  n3(["While"])
  n4(["Call #2"])
  n5(["report #1"])
  n6(["i #1"])
  n7(["Assign #2"])
  n8(["0"])
  n9(["ChargeParam<br>target_voltage 4.2"])
  n10(["procedure (FunctionDef)"])
  n11(["Attribute"])
  n12(["Assign #3"])
  n13(["Compare"])
  n14(["charge"])
  n15(["ImportFrom #1"])
  n16(["ImportFrom #2"])
  n17(["AugAssign"])
  n18(["ImportFrom #3"])
  n19(["i #2"])
  n20(["measure"])
  n21(["Report"])
  n22(["Call #3"])
  n23(["Module"])
  n24(["cycles"])
  n25(["i #3"])
  n26(["report #2"])
  n27(["int"])
  n1 -->|targets| n11
  n1 -->|value| n22
  n2 -->|argument| n9
  n2 -->|func| n14
  n3 -->|body| n2
  n3 -->|body| n17
  n3 -->|test| n13
  n4 -->|func| n21
  n7 -->|targets| n19
  n7 -->|value| n8
  n10 -->|args| n27
  n10 -->|body| n12
  n10 -->|body| n7
  n10 -->|body| n3
  n10 -->|body| n1
  n11 -->|value| n26
  n12 -->|targets| n5
  n12 -->|value| n4
  n13 -->|comparators| n24
  n13 -->|left| n6
  n17 -->|target| n25
  n17 -->|value| n0
  n22 -->|func| n20
  n23 -->|body| n18
  n23 -->|body| n16
  n23 -->|body| n15
  n23 -->|body| n10

What voltage does the procedure charge to, and what class says so?

PREFIX param: <https://w3id.org/awl/py/battery.params/ChargeParam#>

SELECT ?class ?volts WHERE {
  ?node a ?class ; param:target_voltage ?volts .
}
class volts
py:battery.params/ChargeParam 4.2

The tree, located

The same tree with spans on, so every node says where it was written. That is the join key for patching a file in place, for laying a trace over it, and for joining the tree to anything looked up beside it. It is also about half the tree's triples. Every profile turns it on for that reason; the tree above turned it off, which is the only thing that differs between the two.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "@type": "Module",
   "body": [
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
     "@type": "ImportFrom",
     "module": "battery.device",
     "names": ["charge", "measure"],
     "level": 0,
     "order": 0,
     "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
     "@type": "ImportFrom",
     "module": "battery.params",
     "names": ["ChargeParam"],
     "level": 0,
     "order": 1,
     "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#3",
     "@type": "ImportFrom",
     "module": "battery.report",
     "names": ["Report"],
     "level": 0,
     "order": 2,
     "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33}
    },
    {
     "@type": "FunctionDef",
     "name": "procedure",
     "args": [
      {
       "arg": "cycles",
       "annotation": {"var": "int", "span": {"file": "procedure.py", "start_line": 6, "start_col": 22, "end_line": 6, "end_col": 25}}
      }
     ],
     "body": [
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
       "@type": "Assign",
       "targets": [{"var": "report", "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 10}}],
       "value": {
        "@type": "Call",
        "func": {"var": "Report", "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 19}},
        "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21}
       },
       "order": 0,
       "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
       "@type": "Assign",
       "targets": [{"var": "i", "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 5}}],
       "value": {"literal": 0, "span": {"file": "procedure.py", "start_line": 8, "start_col": 8, "end_line": 8, "end_col": 9}},
       "order": 1,
       "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
       "@type": "While",
       "test": {
        "@type": "Compare",
        "left": {"var": "i", "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 11}},
        "ops": ["Lt"],
        "comparators": [{"var": "cycles", "span": {"file": "procedure.py", "start_line": 9, "start_col": 14, "end_line": 9, "end_col": 20}}],
        "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20}
       },
       "body": [
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
         "@type": "Call",
         "func": {"var": "charge", "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 14}},
         "args": [
          {
           "@type": ["ChargeParam"],
           "target_voltage": 4.2,
           "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46}
          }
         ],
         "order": 0,
         "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47}
        },
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
         "@type": "AugAssign",
         "target": {"var": "i", "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 9}},
         "op": "Add",
         "value": {"literal": 1, "span": {"file": "procedure.py", "start_line": 12, "start_col": 13, "end_line": 12, "end_col": 14}},
         "order": 1,
         "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14}
        }
       ],
       "order": 2,
       "span": {"file": "procedure.py", "start_line": 9, "start_col": 4, "end_line": 12, "end_col": 14}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
       "@type": "Assign",
       "targets": [
        {
         "@type": "Attribute",
         "value": {"var": "report", "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 10}},
         "attr": "capacity",
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 19}
        }
       ],
       "value": {
        "@type": "Call",
        "func": {"var": "measure", "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 29}},
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31}
       },
       "order": 3,
       "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 31}
      }
     ],
     "returns": {"literal": null, "span": {"file": "procedure.py", "start_line": 6, "start_col": 30, "end_line": 6, "end_col": 34}},
     "order": 3,
     "span": {"file": "procedure.py", "start_line": 6, "start_col": 0, "end_line": 13, "end_col": 31}
    }
   ]
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix ns1: <https://w3id.org/awl/py/battery.params/ChargeParam#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<https://w3id.org/awl/py/battery.procedure/procedure.step#4> a awl:Assign ;
    awl:order 0 ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] ;
    awl:targets [ awl:span [ awl:endCol 10 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 7 ] ;
            awl:var "report" ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:span [ awl:endCol 19 ;
                            awl:endLine 7 ;
                            awl:file "procedure.py" ;
                            awl:startCol 13 ;
                            awl:startLine 7 ] ;
                    awl:var "Report" ] ;
            awl:span [ awl:endCol 21 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 7 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#5> a awl:Assign ;
    awl:order 1 ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] ;
    awl:targets [ awl:span [ awl:endCol 5 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 8 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 0 ;
            awl:span [ awl:endCol 9 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 8 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#6> a awl:While ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#7> <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ) ;
    awl:order 2 ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 9 ] ;
    awl:test [ a awl:Compare ;
            awl:comparators [ awl:span [ awl:endCol 20 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 14 ;
                            awl:startLine 9 ] ;
                    awl:var "cycles" ] ;
            awl:left [ awl:span [ awl:endCol 11 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 10 ;
                            awl:startLine 9 ] ;
                    awl:var "i" ] ;
            awl:ops "Lt" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#7> a awl:Call ;
    awl:argument ( [ a <https://w3id.org/awl/py/battery.params/ChargeParam> ;
                ns1:target_voltage 4.2e+00 ;
                awl:span [ awl:endCol 46 ;
                        awl:endLine 11 ;
                        awl:file "procedure.py" ;
                        awl:startCol 15 ;
                        awl:startLine 11 ] ] ) ;
    awl:func [ awl:span [ awl:endCol 14 ;
                    awl:endLine 11 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 11 ] ;
            awl:var "charge" ] ;
    awl:order 0 ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#8> a awl:AugAssign ;
    awl:op "Add" ;
    awl:order 1 ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] ;
    awl:target [ awl:span [ awl:endCol 9 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 12 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 1 ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 12 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#9> a awl:Assign ;
    awl:order 3 ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 13 ] ;
    awl:targets [ a awl:Attribute ;
            awl:attr "capacity" ;
            awl:span [ awl:endCol 19 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 13 ] ;
            awl:value [ awl:span [ awl:endCol 10 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 4 ;
                            awl:startLine 13 ] ;
                    awl:var "report" ] ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:span [ awl:endCol 29 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 22 ;
                            awl:startLine 13 ] ;
                    awl:var "measure" ] ;
            awl:span [ awl:endCol 31 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 22 ;
                    awl:startLine 13 ] ] .

<https://w3id.org/awl/py/battery.procedure/step#1> a awl:ImportFrom ;
    awl:level 0 ;
    awl:module "battery.device" ;
    awl:names "charge",
        "measure" ;
    awl:order 0 ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/step#2> a awl:ImportFrom ;
    awl:level 0 ;
    awl:module "battery.params" ;
    awl:names "ChargeParam" ;
    awl:order 1 ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/step#3> a awl:ImportFrom ;
    awl:level 0 ;
    awl:module "battery.report" ;
    awl:names "Report" ;
    awl:order 2 ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

[] a awl:Module ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/step#1> <https://w3id.org/awl/py/battery.procedure/step#2> <https://w3id.org/awl/py/battery.procedure/step#3> [ a awl:FunctionDef ;
                awl:args [ awl:annotation [ awl:span [ awl:endCol 25 ;
                                        awl:endLine 6 ;
                                        awl:file "procedure.py" ;
                                        awl:startCol 22 ;
                                        awl:startLine 6 ] ;
                                awl:var "int" ] ;
                        awl:arg "cycles" ] ;
                awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#4> <https://w3id.org/awl/py/battery.procedure/procedure.step#5> <https://w3id.org/awl/py/battery.procedure/procedure.step#6> <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ) ;
                awl:name "procedure" ;
                awl:order 3 ;
                awl:returns [ awl:span [ awl:endCol 34 ;
                                awl:endLine 6 ;
                                awl:file "procedure.py" ;
                                awl:startCol 30 ;
                                awl:startLine 6 ] ] ;
                awl:span [ awl:endCol 31 ;
                        awl:endLine 13 ;
                        awl:file "procedure.py" ;
                        awl:startCol 0 ;
                        awl:startLine 6 ] ] ) .
graph TD
  n0(["Attribute L13"])
  n1(["report L7"])
  n2(["charge L11"])
  n3(["i L9"])
  n4(["0 L8"])
  n5(["ChargeParam L11<br>target_voltage 4.2"])
  n6(["procedure (FunctionDef) L6"])
  n7(["i L8"])
  n8(["Compare L9"])
  n9(["measure L13"])
  n10(["Report L7"])
  n11(["Call L7"])
  n12(["1 L12"])
  n13(["Module"])
  n14(["cycles L9"])
  n15(["Call L13"])
  n16(["report L13"])
  n17(["int L6"])
  n18(["i L12"])
  n19["Assign L7"]
  n20["Assign L8"]
  n21["While L9"]
  n22["Call L11"]
  n23["AugAssign L12"]
  n24["Assign L13"]
  n25["ImportFrom L1"]
  n26["ImportFrom L2"]
  n27["ImportFrom L3"]
  n0 -->|value| n16
  n6 -->|args| n17
  n6 -->|body| n19
  n6 -->|body| n20
  n6 -->|body| n21
  n6 -->|body| n24
  n8 -->|comparators| n14
  n8 -->|left| n3
  n11 -->|func| n10
  n13 -->|body| n25
  n13 -->|body| n26
  n13 -->|body| n27
  n13 -->|body| n6
  n15 -->|func| n9
  n19 -->|targets| n1
  n19 -->|value| n11
  n20 -->|targets| n7
  n20 -->|value| n4
  n21 -->|body| n22
  n21 -->|body| n23
  n21 -->|test| n8
  n22 -->|argument| n5
  n22 -->|func| n2
  n23 -->|target| n18
  n23 -->|value| n12
  n24 -->|targets| n0
  n24 -->|value| n15

On which line is charge called? The tree alone can only answer about the name as written, which is scope-blind: two functions may both call something called charge.

PREFIX awl: <https://w3id.org/awl/schema/>

SELECT ?line ?column WHERE {
  ?call awl:func [ awl:var "charge" ] ;
        awl:span [ awl:startLine ?line ; awl:startCol ?column ] .
}
line column
11 8

The tree, explained

The same tree again, with trivia on, so each statement carries what was written about it. ast has no comment node, so without this a comment exists only in the file and nothing derived from the tree can see one. Two places hold what belongs to no statement: the end of a block, and the head and tail of the module.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "@type": "Module",
   "body": [
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
     "@type": "ImportFrom",
     "module": "battery.device",
     "names": ["charge", "measure"],
     "level": 0,
     "order": 0,
     "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
     "@type": "ImportFrom",
     "module": "battery.params",
     "names": ["ChargeParam"],
     "level": 0,
     "order": 1,
     "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#3",
     "@type": "ImportFrom",
     "module": "battery.report",
     "names": ["Report"],
     "level": 0,
     "order": 2,
     "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33}
    },
    {
     "@type": "FunctionDef",
     "name": "procedure",
     "args": [
      {
       "arg": "cycles",
       "annotation": {"var": "int", "span": {"file": "procedure.py", "start_line": 6, "start_col": 22, "end_line": 6, "end_col": 25}}
      }
     ],
     "body": [
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
       "@type": "Assign",
       "targets": [{"var": "report", "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 10}}],
       "value": {
        "@type": "Call",
        "func": {"var": "Report", "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 19}},
        "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21}
       },
       "order": 0,
       "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
       "@type": "Assign",
       "targets": [{"var": "i", "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 5}}],
       "value": {"literal": 0, "span": {"file": "procedure.py", "start_line": 8, "start_col": 8, "end_line": 8, "end_col": 9}},
       "order": 1,
       "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
       "@type": "While",
       "test": {
        "@type": "Compare",
        "left": {"var": "i", "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 11}},
        "ops": ["Lt"],
        "comparators": [{"var": "cycles", "span": {"file": "procedure.py", "start_line": 9, "start_col": 14, "end_line": 9, "end_col": 20}}],
        "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20}
       },
       "body": [
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
         "@type": "Call",
         "func": {"var": "charge", "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 14}},
         "args": [
          {
           "@type": ["ChargeParam"],
           "target_voltage": 4.2,
           "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46}
          }
         ],
         "order": 0,
         "comment": {
          "text": "hold the cell at its target until it settles",
          "where": "above",
          "span": {"file": "procedure.py", "start_line": 10, "start_col": 8, "end_line": 10, "end_col": 54}
         },
         "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47}
        },
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
         "@type": "AugAssign",
         "target": {"var": "i", "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 9}},
         "op": "Add",
         "value": {"literal": 1, "span": {"file": "procedure.py", "start_line": 12, "start_col": 13, "end_line": 12, "end_col": 14}},
         "order": 1,
         "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14}
        }
       ],
       "order": 2,
       "span": {"file": "procedure.py", "start_line": 9, "start_col": 4, "end_line": 12, "end_col": 14}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
       "@type": "Assign",
       "targets": [
        {
         "@type": "Attribute",
         "value": {"var": "report", "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 10}},
         "attr": "capacity",
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 19}
        }
       ],
       "value": {
        "@type": "Call",
        "func": {"var": "measure", "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 29}},
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31}
       },
       "order": 3,
       "comment": {
        "text": "what the cell held, once",
        "where": "beside",
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 33, "end_line": 13, "end_col": 59}
       },
       "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 31}
      }
     ],
     "returns": {"literal": null, "span": {"file": "procedure.py", "start_line": 6, "start_col": 30, "end_line": 6, "end_col": 34}},
     "order": 3,
     "span": {"file": "procedure.py", "start_line": 6, "start_col": 0, "end_line": 13, "end_col": 31}
    }
   ]
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix ns1: <https://w3id.org/awl/py/battery.params/ChargeParam#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<https://w3id.org/awl/py/battery.procedure/procedure.step#4> a awl:Assign ;
    awl:order 0 ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] ;
    awl:targets [ awl:span [ awl:endCol 10 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 7 ] ;
            awl:var "report" ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:span [ awl:endCol 19 ;
                            awl:endLine 7 ;
                            awl:file "procedure.py" ;
                            awl:startCol 13 ;
                            awl:startLine 7 ] ;
                    awl:var "Report" ] ;
            awl:span [ awl:endCol 21 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 7 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#5> a awl:Assign ;
    awl:order 1 ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] ;
    awl:targets [ awl:span [ awl:endCol 5 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 8 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 0 ;
            awl:span [ awl:endCol 9 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 8 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#6> a awl:While ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#7> <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ) ;
    awl:order 2 ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 9 ] ;
    awl:test [ a awl:Compare ;
            awl:comparators [ awl:span [ awl:endCol 20 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 14 ;
                            awl:startLine 9 ] ;
                    awl:var "cycles" ] ;
            awl:left [ awl:span [ awl:endCol 11 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 10 ;
                            awl:startLine 9 ] ;
                    awl:var "i" ] ;
            awl:ops "Lt" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#7> a awl:Call ;
    awl:argument ( [ a <https://w3id.org/awl/py/battery.params/ChargeParam> ;
                ns1:target_voltage 4.2e+00 ;
                awl:span [ awl:endCol 46 ;
                        awl:endLine 11 ;
                        awl:file "procedure.py" ;
                        awl:startCol 15 ;
                        awl:startLine 11 ] ] ) ;
    awl:comment [ awl:span [ awl:endCol 54 ;
                    awl:endLine 10 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 10 ] ;
            awl:text "hold the cell at its target until it settles" ;
            awl:where "above" ] ;
    awl:func [ awl:span [ awl:endCol 14 ;
                    awl:endLine 11 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 11 ] ;
            awl:var "charge" ] ;
    awl:order 0 ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#8> a awl:AugAssign ;
    awl:op "Add" ;
    awl:order 1 ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] ;
    awl:target [ awl:span [ awl:endCol 9 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 12 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 1 ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 12 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#9> a awl:Assign ;
    awl:comment [ awl:span [ awl:endCol 59 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 33 ;
                    awl:startLine 13 ] ;
            awl:text "what the cell held, once" ;
            awl:where "beside" ] ;
    awl:order 3 ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 13 ] ;
    awl:targets [ a awl:Attribute ;
            awl:attr "capacity" ;
            awl:span [ awl:endCol 19 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 13 ] ;
            awl:value [ awl:span [ awl:endCol 10 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 4 ;
                            awl:startLine 13 ] ;
                    awl:var "report" ] ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:span [ awl:endCol 29 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 22 ;
                            awl:startLine 13 ] ;
                    awl:var "measure" ] ;
            awl:span [ awl:endCol 31 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 22 ;
                    awl:startLine 13 ] ] .

<https://w3id.org/awl/py/battery.procedure/step#1> a awl:ImportFrom ;
    awl:level 0 ;
    awl:module "battery.device" ;
    awl:names "charge",
        "measure" ;
    awl:order 0 ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/step#2> a awl:ImportFrom ;
    awl:level 0 ;
    awl:module "battery.params" ;
    awl:names "ChargeParam" ;
    awl:order 1 ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/step#3> a awl:ImportFrom ;
    awl:level 0 ;
    awl:module "battery.report" ;
    awl:names "Report" ;
    awl:order 2 ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

[] a awl:Module ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/step#1> <https://w3id.org/awl/py/battery.procedure/step#2> <https://w3id.org/awl/py/battery.procedure/step#3> [ a awl:FunctionDef ;
                awl:args [ awl:annotation [ awl:span [ awl:endCol 25 ;
                                        awl:endLine 6 ;
                                        awl:file "procedure.py" ;
                                        awl:startCol 22 ;
                                        awl:startLine 6 ] ;
                                awl:var "int" ] ;
                        awl:arg "cycles" ] ;
                awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#4> <https://w3id.org/awl/py/battery.procedure/procedure.step#5> <https://w3id.org/awl/py/battery.procedure/procedure.step#6> <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ) ;
                awl:name "procedure" ;
                awl:order 3 ;
                awl:returns [ awl:span [ awl:endCol 34 ;
                                awl:endLine 6 ;
                                awl:file "procedure.py" ;
                                awl:startCol 30 ;
                                awl:startLine 6 ] ] ;
                awl:span [ awl:endCol 31 ;
                        awl:endLine 13 ;
                        awl:file "procedure.py" ;
                        awl:startCol 0 ;
                        awl:startLine 6 ] ] ) .
graph TD
  n0(["Attribute L13"])
  n1(["report L7"])
  n2(["charge L11"])
  n3(["i L9"])
  n4(["0 L8"])
  n5(["ChargeParam L11<br>target_voltage 4.2"])
  n6(["procedure (FunctionDef) L6"])
  n7(["i L8"])
  n8(["Compare L9"])
  n9(["measure L13"])
  n10(["Report L7"])
  n11(["Call L7"])
  n12(["1 L12"])
  n13(["Module"])
  n14(["cycles L9"])
  n15(["Call L13"])
  n16(["report L13"])
  n17(["int L6"])
  n18(["i L12"])
  n19["Assign L7"]
  n20["Assign L8"]
  n21["While L9"]
  n22["Call L11"]
  n23["AugAssign L12"]
  n24["Assign L13"]
  n25["ImportFrom L1"]
  n26["ImportFrom L2"]
  n27["ImportFrom L3"]
  n0 -->|value| n16
  n6 -->|args| n17
  n6 -->|body| n19
  n6 -->|body| n20
  n6 -->|body| n21
  n6 -->|body| n24
  n8 -->|comparators| n14
  n8 -->|left| n3
  n11 -->|func| n10
  n13 -->|body| n25
  n13 -->|body| n26
  n13 -->|body| n27
  n13 -->|body| n6
  n15 -->|func| n9
  n19 -->|targets| n1
  n19 -->|value| n11
  n20 -->|targets| n7
  n20 -->|value| n4
  n21 -->|body| n22
  n21 -->|body| n23
  n21 -->|test| n8
  n22 -->|argument| n5
  n22 -->|func| n2
  n23 -->|target| n18
  n23 -->|value| n12
  n24 -->|targets| n0
  n24 -->|value| n15

What was the author's reason for a step, in their own words?

PREFIX awl: <https://w3id.org/awl/schema/>

SELECT ?text ?where ?line WHERE {
  ?step awl:comment [ awl:text ?text ; awl:where ?where ] ;
        awl:span [ awl:startLine ?line ] .
}
text where line
hold the cell at its target until it settles above 11
what the cell held, once beside 13

The plan

The plan lookup: which step follows which, and under what condition. A loop is found by its back edge and a branch by the definitions its condition reads, never by matching source text.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
   "_type": ["Step", "Unknown"],
   "parser_type_name": "ImportFrom",
   "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42},
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/step#2"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
   "_type": ["Step", "Unknown"],
   "parser_type_name": "ImportFrom",
   "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38},
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/step#3"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/step#3",
   "_type": ["Step", "Unknown"],
   "parser_type_name": "ImportFrom",
   "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33}
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21},
   "callee": "Report",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9},
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
   "_type": ["Step", "ControlStructure"],
   "parser_type_name": "While",
   "span": {"file": "procedure.py", "start_line": 9, "start_col": 4, "end_line": 12, "end_col": 14},
   "condition": {
    "_type": "Call",
    "parser_type_name": "Compare",
    "source_text": "i < cycles",
    "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20},
    "reads": [
     {"@id": "https://w3id.org/awl/py/battery.procedure/procedure.cycles#5"},
     {"@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#7"}
    ]
   },
   "scope": "procedure",
   "when_true": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7"}],
   "when_false": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
   "_type": ["Step", "Call"],
   "parser_type_name": "Expr",
   "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47},
   "callee": "charge",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
   "_type": ["Step", "Call"],
   "parser_type_name": "AugAssign",
   "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14},
   "scope": "procedure",
   "repeat": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 31},
   "callee": "measure",
   "scope": "procedure"
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<https://w3id.org/awl/py/battery.procedure/procedure.step#4> a awl:Call,
        awl:Step ;
    awl:callee "Report" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#5> ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] .

<https://w3id.org/awl/py/battery.procedure/step#1> a awl:Step,
        awl:Unknown ;
    awl:next <https://w3id.org/awl/py/battery.procedure/step#2> ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#5> a awl:Call,
        awl:Step ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#6> ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#7> a awl:Call,
        awl:Step ;
    awl:callee "charge" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ;
    awl:parserTypeName "Expr" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#8> a awl:Call,
        awl:Step ;
    awl:parserTypeName "AugAssign" ;
    awl:repeat <https://w3id.org/awl/py/battery.procedure/procedure.step#6> ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#9> a awl:Call,
        awl:Step ;
    awl:callee "measure" ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 13 ] .

<https://w3id.org/awl/py/battery.procedure/step#2> a awl:Step,
        awl:Unknown ;
    awl:next <https://w3id.org/awl/py/battery.procedure/step#3> ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/step#3> a awl:Step,
        awl:Unknown ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#6> a awl:ControlStructure,
        awl:Step ;
    awl:condition [ a awl:Call ;
            awl:parserTypeName "Compare" ;
            awl:reads <https://w3id.org/awl/py/battery.procedure/procedure.cycles#5>,
                <https://w3id.org/awl/py/battery.procedure/procedure.i#7> ;
            awl:sourceText "i < cycles" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] ;
    awl:parserTypeName "While" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 9 ] ;
    awl:whenFalse <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ;
    awl:whenTrue <https://w3id.org/awl/py/battery.procedure/procedure.step#7> .
graph TD
  n0(["Compare (Call) L9"])
  n1["5"]
  n2["7"]
  n3["Report (Call, Step) L7"]
  n4["Assign (Call, Step) L8"]
  n5["While (ControlStructure, Step) L9"]
  n6["charge (Call, Step) L11"]
  n7["AugAssign (Call, Step) L12"]
  n8["measure (Call, Step) L13"]
  n9["ImportFrom (Step, Unknown) L1"]
  n10["ImportFrom (Step, Unknown) L2"]
  n11["ImportFrom (Step, Unknown) L3"]
  n0 -->|reads| n1
  n0 -->|reads| n2
  n3 -->|next| n4
  n4 -->|next| n5
  n5 -->|condition| n0
  n5 -->|whenFalse| n8
  n5 -->|whenTrue| n6
  n6 -->|next| n7
  n7 -->|repeat| n5
  n9 -->|next| n10
  n10 -->|next| n11

Which steps form the loop, and which edge closes it?

PREFIX awl: <https://w3id.org/awl/schema/>

SELECT ?loop ?body ?back WHERE {
  ?loop awl:whenTrue ?body .
  ?back awl:repeat ?loop .
}
loop body back
py:battery.procedure/procedure.step#6 py:battery.procedure/procedure.step#7 py:battery.procedure/procedure.step#8

The names

The names lookup: what each name in the tree refers to, minted as an identity and carrying the confidence it was reached at. The tree still keeps charge as the word the author wrote, because that is what regenerates the source; beside it, each name reference gains a refers_to, so the same question can be asked by identity instead of by spelling. The name is scope-blind and the identity is not.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "@type": "Module",
   "body": [
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
     "@type": "ImportFrom",
     "module": "battery.device",
     "names": ["charge", "measure"],
     "level": 0,
     "order": 0,
     "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
     "@type": "ImportFrom",
     "module": "battery.params",
     "names": ["ChargeParam"],
     "level": 0,
     "order": 1,
     "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#3",
     "@type": "ImportFrom",
     "module": "battery.report",
     "names": ["Report"],
     "level": 0,
     "order": 2,
     "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33}
    },
    {
     "@type": "FunctionDef",
     "name": "procedure",
     "args": [
      {
       "arg": "cycles",
       "annotation": {"var": "int", "span": {"file": "procedure.py", "start_line": 6, "start_col": 22, "end_line": 6, "end_col": 25}}
      }
     ],
     "body": [
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
       "@type": "Assign",
       "targets": [{"var": "report", "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 10}}],
       "value": {
        "@type": "Call",
        "func": {
         "var": "Report",
         "refers_to": {"@id": "https://w3id.org/awl/py/battery.report/Report"},
         "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 19}
        },
        "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21}
       },
       "order": 0,
       "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
       "@type": "Assign",
       "targets": [{"var": "i", "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 5}}],
       "value": {"literal": 0, "span": {"file": "procedure.py", "start_line": 8, "start_col": 8, "end_line": 8, "end_col": 9}},
       "order": 1,
       "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
       "@type": "While",
       "test": {
        "@type": "Compare",
        "left": {"var": "i", "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 11}},
        "ops": ["Lt"],
        "comparators": [{"var": "cycles", "span": {"file": "procedure.py", "start_line": 9, "start_col": 14, "end_line": 9, "end_col": 20}}],
        "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20}
       },
       "body": [
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
         "@type": "Call",
         "func": {
          "var": "charge",
          "refers_to": {"@id": "https://w3id.org/awl/py/battery.device/charge"},
          "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 14}
         },
         "args": [
          {
           "@type": ["ChargeParam"],
           "target_voltage": 4.2,
           "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46}
          }
         ],
         "order": 0,
         "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47}
        },
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
         "@type": "AugAssign",
         "target": {"var": "i", "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 9}},
         "op": "Add",
         "value": {"literal": 1, "span": {"file": "procedure.py", "start_line": 12, "start_col": 13, "end_line": 12, "end_col": 14}},
         "order": 1,
         "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14}
        }
       ],
       "order": 2,
       "span": {"file": "procedure.py", "start_line": 9, "start_col": 4, "end_line": 12, "end_col": 14}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
       "@type": "Assign",
       "targets": [
        {
         "@type": "Attribute",
         "value": {"var": "report", "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 10}},
         "attr": "capacity",
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 19}
        }
       ],
       "value": {
        "@type": "Call",
        "func": {
         "var": "measure",
         "refers_to": {"@id": "https://w3id.org/awl/py/battery.device/measure"},
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 29}
        },
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31}
       },
       "order": 3,
       "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 31}
      }
     ],
     "returns": {"literal": null, "span": {"file": "procedure.py", "start_line": 6, "start_col": 30, "end_line": 6, "end_col": 34}},
     "order": 3,
     "span": {"file": "procedure.py", "start_line": 6, "start_col": 0, "end_line": 13, "end_col": 31}
    }
   ]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.report/Report",
   "_type": "Binding",
   "local_name": "Report",
   "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.report",
   "symbol": "Report"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.device/charge",
   "_type": "Binding",
   "local_name": "charge",
   "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.device",
   "symbol": "charge"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.params/ChargeParam",
   "_type": "Binding",
   "local_name": "ChargeParam",
   "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.params",
   "symbol": "ChargeParam"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.device/measure",
   "_type": "Binding",
   "local_name": "measure",
   "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.device",
   "symbol": "measure"
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix ns1: <https://w3id.org/awl/py/battery.params/ChargeParam#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<https://w3id.org/awl/py/battery.device/charge> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "charge" ;
    awl:module "battery.device" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] ;
    awl:symbol "charge" .

<https://w3id.org/awl/py/battery.device/measure> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "measure" ;
    awl:module "battery.device" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 22 ;
            awl:startLine 13 ] ;
    awl:symbol "measure" .

<https://w3id.org/awl/py/battery.params/ChargeParam> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "ChargeParam" ;
    awl:module "battery.params" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 46 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 15 ;
            awl:startLine 11 ] ;
    awl:symbol "ChargeParam" .

<https://w3id.org/awl/py/battery.procedure/procedure.step#4> a awl:Assign ;
    awl:order 0 ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] ;
    awl:targets [ awl:span [ awl:endCol 10 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 7 ] ;
            awl:var "report" ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.report/Report> ;
                    awl:span [ awl:endCol 19 ;
                            awl:endLine 7 ;
                            awl:file "procedure.py" ;
                            awl:startCol 13 ;
                            awl:startLine 7 ] ;
                    awl:var "Report" ] ;
            awl:span [ awl:endCol 21 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 7 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#5> a awl:Assign ;
    awl:order 1 ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] ;
    awl:targets [ awl:span [ awl:endCol 5 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 8 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 0 ;
            awl:span [ awl:endCol 9 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 8 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#6> a awl:While ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#7> <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ) ;
    awl:order 2 ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 9 ] ;
    awl:test [ a awl:Compare ;
            awl:comparators [ awl:span [ awl:endCol 20 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 14 ;
                            awl:startLine 9 ] ;
                    awl:var "cycles" ] ;
            awl:left [ awl:span [ awl:endCol 11 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 10 ;
                            awl:startLine 9 ] ;
                    awl:var "i" ] ;
            awl:ops "Lt" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#7> a awl:Call ;
    awl:argument ( [ a <https://w3id.org/awl/py/battery.params/ChargeParam> ;
                ns1:target_voltage 4.2e+00 ;
                awl:span [ awl:endCol 46 ;
                        awl:endLine 11 ;
                        awl:file "procedure.py" ;
                        awl:startCol 15 ;
                        awl:startLine 11 ] ] ) ;
    awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.device/charge> ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 11 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 11 ] ;
            awl:var "charge" ] ;
    awl:order 0 ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#8> a awl:AugAssign ;
    awl:op "Add" ;
    awl:order 1 ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] ;
    awl:target [ awl:span [ awl:endCol 9 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 12 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 1 ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 12 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#9> a awl:Assign ;
    awl:order 3 ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 13 ] ;
    awl:targets [ a awl:Attribute ;
            awl:attr "capacity" ;
            awl:span [ awl:endCol 19 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 13 ] ;
            awl:value [ awl:span [ awl:endCol 10 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 4 ;
                            awl:startLine 13 ] ;
                    awl:var "report" ] ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.device/measure> ;
                    awl:span [ awl:endCol 29 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 22 ;
                            awl:startLine 13 ] ;
                    awl:var "measure" ] ;
            awl:span [ awl:endCol 31 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 22 ;
                    awl:startLine 13 ] ] .

<https://w3id.org/awl/py/battery.procedure/step#1> a awl:ImportFrom ;
    awl:level 0 ;
    awl:module "battery.device" ;
    awl:names "charge",
        "measure" ;
    awl:order 0 ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/step#2> a awl:ImportFrom ;
    awl:level 0 ;
    awl:module "battery.params" ;
    awl:names "ChargeParam" ;
    awl:order 1 ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/step#3> a awl:ImportFrom ;
    awl:level 0 ;
    awl:module "battery.report" ;
    awl:names "Report" ;
    awl:order 2 ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

<https://w3id.org/awl/py/battery.report/Report> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "Report" ;
    awl:module "battery.report" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 13 ;
            awl:startLine 7 ] ;
    awl:symbol "Report" .

[] a awl:Module ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/step#1> <https://w3id.org/awl/py/battery.procedure/step#2> <https://w3id.org/awl/py/battery.procedure/step#3> [ a awl:FunctionDef ;
                awl:args [ awl:annotation [ awl:span [ awl:endCol 25 ;
                                        awl:endLine 6 ;
                                        awl:file "procedure.py" ;
                                        awl:startCol 22 ;
                                        awl:startLine 6 ] ;
                                awl:var "int" ] ;
                        awl:arg "cycles" ] ;
                awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#4> <https://w3id.org/awl/py/battery.procedure/procedure.step#5> <https://w3id.org/awl/py/battery.procedure/procedure.step#6> <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ) ;
                awl:name "procedure" ;
                awl:order 3 ;
                awl:returns [ awl:span [ awl:endCol 34 ;
                                awl:endLine 6 ;
                                awl:file "procedure.py" ;
                                awl:startCol 30 ;
                                awl:startLine 6 ] ] ;
                awl:span [ awl:endCol 31 ;
                        awl:endLine 13 ;
                        awl:file "procedure.py" ;
                        awl:startCol 0 ;
                        awl:startLine 6 ] ] ) .
graph TD
  n0(["Attribute L13"])
  n1(["Report L7"])
  n2(["report L7"])
  n3(["i L9"])
  n4(["0 L8"])
  n5(["ChargeParam L11<br>target_voltage 4.2"])
  n6(["procedure (FunctionDef) L6"])
  n7(["i L8"])
  n8(["charge L11"])
  n9(["Compare L9"])
  n10(["Call L7"])
  n11(["1 L12"])
  n12(["Module"])
  n13(["cycles L9"])
  n14(["Call L13"])
  n15(["report L13"])
  n16(["int L6"])
  n17(["i L12"])
  n18(["measure L13"])
  n19["charge (Binding) L11"]
  n20["measure (Binding) L13"]
  n21["ChargeParam (Binding) L11"]
  n22["Assign L7"]
  n23["Assign L8"]
  n24["While L9"]
  n25["Call L11"]
  n26["AugAssign L12"]
  n27["Assign L13"]
  n28["ImportFrom L1"]
  n29["ImportFrom L2"]
  n30["ImportFrom L3"]
  n31["Report (Binding) L7"]
  n0 -->|value| n15
  n1 -->|refersTo| n31
  n5 -->|type| n21
  n6 -->|args| n16
  n6 -->|body| n22
  n6 -->|body| n23
  n6 -->|body| n24
  n6 -->|body| n27
  n8 -->|refersTo| n19
  n9 -->|comparators| n13
  n9 -->|left| n3
  n10 -->|func| n1
  n12 -->|body| n28
  n12 -->|body| n29
  n12 -->|body| n30
  n12 -->|body| n6
  n14 -->|func| n18
  n18 -->|refersTo| n20
  n22 -->|targets| n2
  n22 -->|value| n10
  n23 -->|targets| n7
  n23 -->|value| n4
  n24 -->|body| n25
  n24 -->|body| n26
  n24 -->|test| n9
  n25 -->|argument| n5
  n25 -->|func| n8
  n26 -->|target| n17
  n26 -->|value| n11
  n27 -->|targets| n0
  n27 -->|value| n14

On which line is this charge called, the one imported from battery.device?

PREFIX awl: <https://w3id.org/awl/schema/>

SELECT ?line ?column WHERE {
  ?call awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.device/charge> ] ;
        awl:span [ awl:startLine ?line ; awl:startCol ?column ] .
}
line column
11 8

The writes

The writes lookup: which typed member a value was written to. report.capacity resolves through the annotation on Report, so the graph names the member and its range rather than the variable that happened to hold it.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "_type": "Write",
   "path": "report.capacity",
   "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 31},
   "written_by": "measure",
   "confidence": "INFERRED",
   "root_type": "https://w3id.org/awl/py/battery.report/Report",
   "member_of": "https://w3id.org/awl/py/battery.report/Report",
   "member": "https://w3id.org/awl/py/battery.report/Report/capacity",
   "member_path": "Report.capacity",
   "range": "https://w3id.org/awl/py/battery.report/Capacity",
   "range_name": "Capacity"
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

[] a awl:Write ;
    awl:confidence "INFERRED" ;
    awl:member <https://w3id.org/awl/py/battery.report/Report/capacity> ;
    awl:memberOf <https://w3id.org/awl/py/battery.report/Report> ;
    awl:memberPath "Report.capacity" ;
    awl:path "report.capacity" ;
    awl:range <https://w3id.org/awl/py/battery.report/Capacity> ;
    awl:rangeName "Capacity" ;
    awl:rootType <https://w3id.org/awl/py/battery.report/Report> ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 13 ] ;
    awl:writtenBy "measure" .
graph TD
  n0(["Write L13"])
  n1["Capacity"]
  n2["Report"]
  n3["capacity"]
  n0 -->|member| n3
  n0 -->|memberOf| n2
  n0 -->|range| n1
  n0 -->|rootType| n2

Where was a Capacity written, and by what?

PREFIX awl: <https://w3id.org/awl/schema/>
PREFIX report: <https://w3id.org/awl/py/battery.report/>

SELECT ?member ?by ?confidence WHERE {
  ?write awl:memberPath ?member ; awl:writtenBy ?by ; awl:confidence ?confidence ;
         awl:range report:Capacity .
}
member by confidence
Report.capacity measure INFERRED

The provenance

The definitions lookup: where each value came from. Set-valued at a join, so a variable assigned in more than one place keeps every definition rather than the last one seen.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/charge#1",
   "_type": "Definition",
   "name": "charge",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42},
   "produced_by": "battery.device.charge",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/measure#2",
   "_type": "Definition",
   "name": "measure",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42},
   "produced_by": "battery.device.measure",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/ChargeParam#3",
   "_type": "Definition",
   "name": "ChargeParam",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38},
   "produced_by": "battery.params.ChargeParam",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/Report#4",
   "_type": "Definition",
   "name": "Report",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33},
   "produced_by": "battery.report.Report",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.cycles#5",
   "_type": "Definition",
   "name": "cycles",
   "kind": "parameter",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 6, "start_col": 14, "end_line": 6, "end_col": 25},
   "produced_by": null,
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.report#6",
   "_type": "Definition",
   "name": "report",
   "kind": "assign",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21},
   "produced_by": "Report",
   "depends_on": ["https://w3id.org/awl/py/battery.procedure/Report#4"]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#7",
   "_type": "Definition",
   "name": "i",
   "kind": "assign",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9},
   "produced_by": null,
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#8",
   "_type": "Definition",
   "name": "i",
   "kind": "augmented",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14},
   "produced_by": null,
   "depends_on": ["https://w3id.org/awl/py/battery.procedure/procedure.i#7"]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#9",
   "_type": "Definition",
   "name": "i",
   "kind": "augmented",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14},
   "produced_by": null,
   "depends_on": ["https://w3id.org/awl/py/battery.procedure/procedure.i#7", "https://w3id.org/awl/py/battery.procedure/procedure.i#8"]
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<https://w3id.org/awl/py/battery.procedure/ChargeParam#3> a awl:Definition ;
    awl:kind "import" ;
    awl:name "ChargeParam" ;
    awl:producedBy "battery.params.ChargeParam" ;
    awl:scope "" ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/charge#1> a awl:Definition ;
    awl:kind "import" ;
    awl:name "charge" ;
    awl:producedBy "battery.device.charge" ;
    awl:scope "" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/measure#2> a awl:Definition ;
    awl:kind "import" ;
    awl:name "measure" ;
    awl:producedBy "battery.device.measure" ;
    awl:scope "" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.cycles#5> a awl:Definition ;
    awl:kind "parameter" ;
    awl:name "cycles" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 25 ;
            awl:endLine 6 ;
            awl:file "procedure.py" ;
            awl:startCol 14 ;
            awl:startLine 6 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.i#9> a awl:Definition ;
    awl:dependsOn <https://w3id.org/awl/py/battery.procedure/procedure.i#7>,
        <https://w3id.org/awl/py/battery.procedure/procedure.i#8> ;
    awl:kind "augmented" ;
    awl:name "i" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.report#6> a awl:Definition ;
    awl:dependsOn <https://w3id.org/awl/py/battery.procedure/Report#4> ;
    awl:kind "assign" ;
    awl:name "report" ;
    awl:producedBy "Report" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] .

<https://w3id.org/awl/py/battery.procedure/Report#4> a awl:Definition ;
    awl:kind "import" ;
    awl:name "Report" ;
    awl:producedBy "battery.report.Report" ;
    awl:scope "" ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.i#8> a awl:Definition ;
    awl:dependsOn <https://w3id.org/awl/py/battery.procedure/procedure.i#7> ;
    awl:kind "augmented" ;
    awl:name "i" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.i#7> a awl:Definition ;
    awl:kind "assign" ;
    awl:name "i" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] .
graph TD
  n0["ChargeParam (Definition) L2 import"]
  n1["Report (Definition) L3 import"]
  n2["charge (Definition) L1 import"]
  n3["measure (Definition) L1 import"]
  n4["cycles (Definition) L6 parameter"]
  n5["i (Definition) L8 assign"]
  n6["i (Definition) L12 augmented #8"]
  n7["i (Definition) L12 augmented #9"]
  n8["report (Definition) L7 assign"]
  n6 -->|dependsOn| n5
  n7 -->|dependsOn| n5
  n7 -->|dependsOn| n6
  n8 -->|dependsOn| n1

Which name has more than one definition, and how many?

PREFIX awl: <https://w3id.org/awl/schema/>

SELECT ?name (COUNT(?definition) AS ?definitions) WHERE {
  ?definition a awl:Definition ; awl:name ?name .
}
GROUP BY ?name
HAVING (COUNT(?definition) > 1)
name definitions
i 3

Combined

Each of these adds to the one before it, ending with what the ast profile produces. Spans are on throughout, because a span is what locates a node in the file it came from, and because naming statements and carrying their comments are both placed against it.

Tree and plan

What was written, and how control moves through it. Not two graphs side by side: a statement carries the identity the plan mints for it, so the step and the statement are one node and the loop's when_true lands on the node holding the call. Asking this used to mean matching four span numbers to say the same statement.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "@type": "Module",
   "body": [
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
     "@type": "ImportFrom",
     "module": "battery.device",
     "names": ["charge", "measure"],
     "level": 0,
     "order": 0,
     "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
     "@type": "ImportFrom",
     "module": "battery.params",
     "names": ["ChargeParam"],
     "level": 0,
     "order": 1,
     "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#3",
     "@type": "ImportFrom",
     "module": "battery.report",
     "names": ["Report"],
     "level": 0,
     "order": 2,
     "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33}
    },
    {
     "@type": "FunctionDef",
     "name": "procedure",
     "args": [
      {
       "arg": "cycles",
       "annotation": {"var": "int", "span": {"file": "procedure.py", "start_line": 6, "start_col": 22, "end_line": 6, "end_col": 25}}
      }
     ],
     "body": [
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
       "@type": "Assign",
       "targets": [{"var": "report", "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 10}}],
       "value": {
        "@type": "Call",
        "func": {
         "var": "Report",
         "refers_to": {"@id": "https://w3id.org/awl/py/battery.report/Report"},
         "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 19}
        },
        "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21}
       },
       "order": 0,
       "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
       "@type": "Assign",
       "targets": [{"var": "i", "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 5}}],
       "value": {"literal": 0, "span": {"file": "procedure.py", "start_line": 8, "start_col": 8, "end_line": 8, "end_col": 9}},
       "order": 1,
       "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
       "@type": "While",
       "test": {
        "@type": "Compare",
        "left": {"var": "i", "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 11}},
        "ops": ["Lt"],
        "comparators": [{"var": "cycles", "span": {"file": "procedure.py", "start_line": 9, "start_col": 14, "end_line": 9, "end_col": 20}}],
        "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20}
       },
       "body": [
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
         "@type": "Call",
         "func": {
          "var": "charge",
          "refers_to": {"@id": "https://w3id.org/awl/py/battery.device/charge"},
          "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 14}
         },
         "args": [
          {
           "@type": ["ChargeParam"],
           "target_voltage": 4.2,
           "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46}
          }
         ],
         "order": 0,
         "comment": {
          "text": "hold the cell at its target until it settles",
          "where": "above",
          "span": {"file": "procedure.py", "start_line": 10, "start_col": 8, "end_line": 10, "end_col": 54}
         },
         "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47}
        },
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
         "@type": "AugAssign",
         "target": {"var": "i", "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 9}},
         "op": "Add",
         "value": {"literal": 1, "span": {"file": "procedure.py", "start_line": 12, "start_col": 13, "end_line": 12, "end_col": 14}},
         "order": 1,
         "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14}
        }
       ],
       "order": 2,
       "span": {"file": "procedure.py", "start_line": 9, "start_col": 4, "end_line": 12, "end_col": 14}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
       "@type": "Assign",
       "targets": [
        {
         "@type": "Attribute",
         "value": {"var": "report", "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 10}},
         "attr": "capacity",
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 19}
        }
       ],
       "value": {
        "@type": "Call",
        "func": {
         "var": "measure",
         "refers_to": {"@id": "https://w3id.org/awl/py/battery.device/measure"},
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 29}
        },
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31}
       },
       "order": 3,
       "comment": {
        "text": "what the cell held, once",
        "where": "beside",
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 33, "end_line": 13, "end_col": 59}
       },
       "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 31}
      }
     ],
     "returns": {"literal": null, "span": {"file": "procedure.py", "start_line": 6, "start_col": 30, "end_line": 6, "end_col": 34}},
     "order": 3,
     "span": {"file": "procedure.py", "start_line": 6, "start_col": 0, "end_line": 13, "end_col": 31}
    }
   ]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
   "_type": ["Step", "Unknown"],
   "parser_type_name": "ImportFrom",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/step#2"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
   "_type": ["Step", "Unknown"],
   "parser_type_name": "ImportFrom",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/step#3"}]
  },
  {"@id": "https://w3id.org/awl/py/battery.procedure/step#3", "_type": ["Step", "Unknown"], "parser_type_name": "ImportFrom"},
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "callee": "Report",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
   "_type": ["Step", "ControlStructure"],
   "parser_type_name": "While",
   "condition": {
    "_type": "Call",
    "parser_type_name": "Compare",
    "source_text": "i < cycles",
    "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20},
    "reads": [
     {"@id": "https://w3id.org/awl/py/battery.procedure/procedure.cycles#5"},
     {"@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#7"}
    ]
   },
   "scope": "procedure",
   "when_true": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7"}],
   "when_false": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
   "_type": ["Step", "Call"],
   "parser_type_name": "Expr",
   "callee": "charge",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
   "_type": ["Step", "Call"],
   "parser_type_name": "AugAssign",
   "scope": "procedure",
   "repeat": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "callee": "measure",
   "scope": "procedure"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.report/Report",
   "_type": "Binding",
   "local_name": "Report",
   "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.report",
   "symbol": "Report"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.device/charge",
   "_type": "Binding",
   "local_name": "charge",
   "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.device",
   "symbol": "charge"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.params/ChargeParam",
   "_type": "Binding",
   "local_name": "ChargeParam",
   "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.params",
   "symbol": "ChargeParam"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.device/measure",
   "_type": "Binding",
   "local_name": "measure",
   "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.device",
   "symbol": "measure"
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix ns1: <https://w3id.org/awl/py/battery.params/ChargeParam#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<https://w3id.org/awl/py/battery.device/charge> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "charge" ;
    awl:module "battery.device" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] ;
    awl:symbol "charge" .

<https://w3id.org/awl/py/battery.device/measure> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "measure" ;
    awl:module "battery.device" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 22 ;
            awl:startLine 13 ] ;
    awl:symbol "measure" .

<https://w3id.org/awl/py/battery.params/ChargeParam> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "ChargeParam" ;
    awl:module "battery.params" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 46 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 15 ;
            awl:startLine 11 ] ;
    awl:symbol "ChargeParam" .

<https://w3id.org/awl/py/battery.procedure/procedure.step#4> a awl:Assign,
        awl:Call,
        awl:Step ;
    awl:callee "Report" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#5> ;
    awl:order 0 ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] ;
    awl:targets [ awl:span [ awl:endCol 10 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 7 ] ;
            awl:var "report" ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.report/Report> ;
                    awl:span [ awl:endCol 19 ;
                            awl:endLine 7 ;
                            awl:file "procedure.py" ;
                            awl:startCol 13 ;
                            awl:startLine 7 ] ;
                    awl:var "Report" ] ;
            awl:span [ awl:endCol 21 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 7 ] ] .

<https://w3id.org/awl/py/battery.procedure/step#1> a awl:ImportFrom,
        awl:Step,
        awl:Unknown ;
    awl:level 0 ;
    awl:module "battery.device" ;
    awl:names "charge",
        "measure" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/step#2> ;
    awl:order 0 ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.report/Report> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "Report" ;
    awl:module "battery.report" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 13 ;
            awl:startLine 7 ] ;
    awl:symbol "Report" .

<https://w3id.org/awl/py/battery.procedure/procedure.step#5> a awl:Assign,
        awl:Call,
        awl:Step ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#6> ;
    awl:order 1 ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] ;
    awl:targets [ awl:span [ awl:endCol 5 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 8 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 0 ;
            awl:span [ awl:endCol 9 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 8 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#7> a awl:Call,
        awl:Step ;
    awl:argument ( [ a <https://w3id.org/awl/py/battery.params/ChargeParam> ;
                ns1:target_voltage 4.2e+00 ;
                awl:span [ awl:endCol 46 ;
                        awl:endLine 11 ;
                        awl:file "procedure.py" ;
                        awl:startCol 15 ;
                        awl:startLine 11 ] ] ) ;
    awl:callee "charge" ;
    awl:comment [ awl:span [ awl:endCol 54 ;
                    awl:endLine 10 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 10 ] ;
            awl:text "hold the cell at its target until it settles" ;
            awl:where "above" ] ;
    awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.device/charge> ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 11 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 11 ] ;
            awl:var "charge" ] ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ;
    awl:order 0 ;
    awl:parserTypeName "Expr" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#8> a awl:AugAssign,
        awl:Call,
        awl:Step ;
    awl:op "Add" ;
    awl:order 1 ;
    awl:parserTypeName "AugAssign" ;
    awl:repeat <https://w3id.org/awl/py/battery.procedure/procedure.step#6> ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] ;
    awl:target [ awl:span [ awl:endCol 9 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 12 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 1 ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 12 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#9> a awl:Assign,
        awl:Call,
        awl:Step ;
    awl:callee "measure" ;
    awl:comment [ awl:span [ awl:endCol 59 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 33 ;
                    awl:startLine 13 ] ;
            awl:text "what the cell held, once" ;
            awl:where "beside" ] ;
    awl:order 3 ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 13 ] ;
    awl:targets [ a awl:Attribute ;
            awl:attr "capacity" ;
            awl:span [ awl:endCol 19 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 13 ] ;
            awl:value [ awl:span [ awl:endCol 10 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 4 ;
                            awl:startLine 13 ] ;
                    awl:var "report" ] ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.device/measure> ;
                    awl:span [ awl:endCol 29 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 22 ;
                            awl:startLine 13 ] ;
                    awl:var "measure" ] ;
            awl:span [ awl:endCol 31 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 22 ;
                    awl:startLine 13 ] ] .

<https://w3id.org/awl/py/battery.procedure/step#2> a awl:ImportFrom,
        awl:Step,
        awl:Unknown ;
    awl:level 0 ;
    awl:module "battery.params" ;
    awl:names "ChargeParam" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/step#3> ;
    awl:order 1 ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/step#3> a awl:ImportFrom,
        awl:Step,
        awl:Unknown ;
    awl:level 0 ;
    awl:module "battery.report" ;
    awl:names "Report" ;
    awl:order 2 ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#6> a awl:ControlStructure,
        awl:Step,
        awl:While ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#7> <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ) ;
    awl:condition [ a awl:Call ;
            awl:parserTypeName "Compare" ;
            awl:reads <https://w3id.org/awl/py/battery.procedure/procedure.cycles#5>,
                <https://w3id.org/awl/py/battery.procedure/procedure.i#7> ;
            awl:sourceText "i < cycles" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] ;
    awl:order 2 ;
    awl:parserTypeName "While" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 9 ] ;
    awl:test [ a awl:Compare ;
            awl:comparators [ awl:span [ awl:endCol 20 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 14 ;
                            awl:startLine 9 ] ;
                    awl:var "cycles" ] ;
            awl:left [ awl:span [ awl:endCol 11 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 10 ;
                            awl:startLine 9 ] ;
                    awl:var "i" ] ;
            awl:ops "Lt" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] ;
    awl:whenFalse <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ;
    awl:whenTrue <https://w3id.org/awl/py/battery.procedure/procedure.step#7> .

[] a awl:Module ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/step#1> <https://w3id.org/awl/py/battery.procedure/step#2> <https://w3id.org/awl/py/battery.procedure/step#3> [ a awl:FunctionDef ;
                awl:args [ awl:annotation [ awl:span [ awl:endCol 25 ;
                                        awl:endLine 6 ;
                                        awl:file "procedure.py" ;
                                        awl:startCol 22 ;
                                        awl:startLine 6 ] ;
                                awl:var "int" ] ;
                        awl:arg "cycles" ] ;
                awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#4> <https://w3id.org/awl/py/battery.procedure/procedure.step#5> <https://w3id.org/awl/py/battery.procedure/procedure.step#6> <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ) ;
                awl:name "procedure" ;
                awl:order 3 ;
                awl:returns [ awl:span [ awl:endCol 34 ;
                                awl:endLine 6 ;
                                awl:file "procedure.py" ;
                                awl:startCol 30 ;
                                awl:startLine 6 ] ] ;
                awl:span [ awl:endCol 31 ;
                        awl:endLine 13 ;
                        awl:file "procedure.py" ;
                        awl:startCol 0 ;
                        awl:startLine 6 ] ] ) .
graph TD
  n0(["i L12"])
  n1(["Call L13"])
  n2(["1 L12"])
  n3(["int L6"])
  n4(["ChargeParam L11<br>target_voltage 4.2"])
  n5(["Attribute L13"])
  n6(["report L7"])
  n7(["measure L13"])
  n8(["report L13"])
  n9(["0 L8"])
  n10(["Report L7"])
  n11(["procedure (FunctionDef) L6"])
  n12(["charge L11"])
  n13(["Compare L9"])
  n14(["i L8"])
  n15(["Compare (Call) L9"])
  n16(["Module"])
  n17(["Call L7"])
  n18(["i L9"])
  n19(["cycles L9"])
  n20["charge (Binding) L11"]
  n21["measure (Binding) L13"]
  n22["ChargeParam (Binding) L11"]
  n23["5"]
  n24["7"]
  n25["Report (Assign, Call, Step) L7"]
  n26["Assign (Assign, Call, Step) L8"]
  n27["While (ControlStructure, Step, While) L9"]
  n28["charge (Call, Step) L11"]
  n29["AugAssign (AugAssign, Call, Step) L12"]
  n30["measure (Assign, Call, Step) L13"]
  n31["ImportFrom (ImportFrom, Step, Unknown) L1"]
  n32["ImportFrom (ImportFrom, Step, Unknown) L2"]
  n33["ImportFrom (ImportFrom, Step, Unknown) L3"]
  n34["Report (Binding) L7"]
  n1 -->|func| n7
  n4 -->|type| n22
  n5 -->|value| n8
  n7 -->|refersTo| n21
  n10 -->|refersTo| n34
  n11 -->|args| n3
  n11 -->|body| n25
  n11 -->|body| n26
  n11 -->|body| n27
  n11 -->|body| n30
  n12 -->|refersTo| n20
  n13 -->|comparators| n19
  n13 -->|left| n18
  n15 -->|reads| n23
  n15 -->|reads| n24
  n16 -->|body| n31
  n16 -->|body| n32
  n16 -->|body| n33
  n16 -->|body| n11
  n17 -->|func| n10
  n25 -->|next| n26
  n25 -->|targets| n6
  n25 -->|value| n17
  n26 -->|next| n27
  n26 -->|targets| n14
  n26 -->|value| n9
  n27 -->|body| n28
  n27 -->|body| n29
  n27 -->|condition| n15
  n27 -->|test| n13
  n27 -->|whenFalse| n30
  n27 -->|whenTrue| n28
  n28 -->|argument| n4
  n28 -->|func| n12
  n28 -->|next| n29
  n29 -->|repeat| n27
  n29 -->|target| n0
  n29 -->|value| n2
  n30 -->|targets| n5
  n30 -->|value| n1
  n31 -->|next| n32
  n32 -->|next| n33

Which function does the loop body call, by identity rather than by name?

PREFIX awl: <https://w3id.org/awl/schema/>

SELECT ?step ?callee WHERE {
  ?loop awl:whenTrue ?step .
  ?step awl:func [ awl:refersTo ?callee ] .
}
step callee
py:battery.procedure/procedure.step#7 py:battery.device/charge

Tree, plan and provenance

Adds where each value came from, so the name a step reads can be followed back to the definitions that could have produced it.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "@type": "Module",
   "body": [
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
     "@type": "ImportFrom",
     "module": "battery.device",
     "names": ["charge", "measure"],
     "level": 0,
     "order": 0,
     "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
     "@type": "ImportFrom",
     "module": "battery.params",
     "names": ["ChargeParam"],
     "level": 0,
     "order": 1,
     "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#3",
     "@type": "ImportFrom",
     "module": "battery.report",
     "names": ["Report"],
     "level": 0,
     "order": 2,
     "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33}
    },
    {
     "@type": "FunctionDef",
     "name": "procedure",
     "args": [
      {
       "arg": "cycles",
       "annotation": {"var": "int", "span": {"file": "procedure.py", "start_line": 6, "start_col": 22, "end_line": 6, "end_col": 25}}
      }
     ],
     "body": [
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
       "@type": "Assign",
       "targets": [{"var": "report", "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 10}}],
       "value": {
        "@type": "Call",
        "func": {
         "var": "Report",
         "refers_to": {"@id": "https://w3id.org/awl/py/battery.report/Report"},
         "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 19}
        },
        "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21}
       },
       "order": 0,
       "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
       "@type": "Assign",
       "targets": [{"var": "i", "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 5}}],
       "value": {"literal": 0, "span": {"file": "procedure.py", "start_line": 8, "start_col": 8, "end_line": 8, "end_col": 9}},
       "order": 1,
       "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
       "@type": "While",
       "test": {
        "@type": "Compare",
        "left": {"var": "i", "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 11}},
        "ops": ["Lt"],
        "comparators": [{"var": "cycles", "span": {"file": "procedure.py", "start_line": 9, "start_col": 14, "end_line": 9, "end_col": 20}}],
        "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20}
       },
       "body": [
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
         "@type": "Call",
         "func": {
          "var": "charge",
          "refers_to": {"@id": "https://w3id.org/awl/py/battery.device/charge"},
          "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 14}
         },
         "args": [
          {
           "@type": ["ChargeParam"],
           "target_voltage": 4.2,
           "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46}
          }
         ],
         "order": 0,
         "comment": {
          "text": "hold the cell at its target until it settles",
          "where": "above",
          "span": {"file": "procedure.py", "start_line": 10, "start_col": 8, "end_line": 10, "end_col": 54}
         },
         "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47}
        },
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
         "@type": "AugAssign",
         "target": {"var": "i", "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 9}},
         "op": "Add",
         "value": {"literal": 1, "span": {"file": "procedure.py", "start_line": 12, "start_col": 13, "end_line": 12, "end_col": 14}},
         "order": 1,
         "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14}
        }
       ],
       "order": 2,
       "span": {"file": "procedure.py", "start_line": 9, "start_col": 4, "end_line": 12, "end_col": 14}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
       "@type": "Assign",
       "targets": [
        {
         "@type": "Attribute",
         "value": {"var": "report", "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 10}},
         "attr": "capacity",
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 19}
        }
       ],
       "value": {
        "@type": "Call",
        "func": {
         "var": "measure",
         "refers_to": {"@id": "https://w3id.org/awl/py/battery.device/measure"},
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 29}
        },
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31}
       },
       "order": 3,
       "comment": {
        "text": "what the cell held, once",
        "where": "beside",
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 33, "end_line": 13, "end_col": 59}
       },
       "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 31}
      }
     ],
     "returns": {"literal": null, "span": {"file": "procedure.py", "start_line": 6, "start_col": 30, "end_line": 6, "end_col": 34}},
     "order": 3,
     "span": {"file": "procedure.py", "start_line": 6, "start_col": 0, "end_line": 13, "end_col": 31}
    }
   ]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
   "_type": ["Step", "Unknown"],
   "parser_type_name": "ImportFrom",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/step#2"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
   "_type": ["Step", "Unknown"],
   "parser_type_name": "ImportFrom",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/step#3"}]
  },
  {"@id": "https://w3id.org/awl/py/battery.procedure/step#3", "_type": ["Step", "Unknown"], "parser_type_name": "ImportFrom"},
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "callee": "Report",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
   "_type": ["Step", "ControlStructure"],
   "parser_type_name": "While",
   "condition": {
    "_type": "Call",
    "parser_type_name": "Compare",
    "source_text": "i < cycles",
    "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20},
    "reads": [
     {"@id": "https://w3id.org/awl/py/battery.procedure/procedure.cycles#5"},
     {"@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#7"}
    ]
   },
   "scope": "procedure",
   "when_true": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7"}],
   "when_false": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
   "_type": ["Step", "Call"],
   "parser_type_name": "Expr",
   "callee": "charge",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
   "_type": ["Step", "Call"],
   "parser_type_name": "AugAssign",
   "scope": "procedure",
   "repeat": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "callee": "measure",
   "scope": "procedure"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.report/Report",
   "_type": "Binding",
   "local_name": "Report",
   "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.report",
   "symbol": "Report"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.device/charge",
   "_type": "Binding",
   "local_name": "charge",
   "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.device",
   "symbol": "charge"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.params/ChargeParam",
   "_type": "Binding",
   "local_name": "ChargeParam",
   "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.params",
   "symbol": "ChargeParam"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.device/measure",
   "_type": "Binding",
   "local_name": "measure",
   "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.device",
   "symbol": "measure"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/charge#1",
   "_type": "Definition",
   "name": "charge",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42},
   "produced_by": "battery.device.charge",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/measure#2",
   "_type": "Definition",
   "name": "measure",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42},
   "produced_by": "battery.device.measure",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/ChargeParam#3",
   "_type": "Definition",
   "name": "ChargeParam",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38},
   "produced_by": "battery.params.ChargeParam",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/Report#4",
   "_type": "Definition",
   "name": "Report",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33},
   "produced_by": "battery.report.Report",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.cycles#5",
   "_type": "Definition",
   "name": "cycles",
   "kind": "parameter",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 6, "start_col": 14, "end_line": 6, "end_col": 25},
   "produced_by": null,
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.report#6",
   "_type": "Definition",
   "name": "report",
   "kind": "assign",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21},
   "produced_by": "Report",
   "depends_on": ["https://w3id.org/awl/py/battery.procedure/Report#4"]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#7",
   "_type": "Definition",
   "name": "i",
   "kind": "assign",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9},
   "produced_by": null,
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#8",
   "_type": "Definition",
   "name": "i",
   "kind": "augmented",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14},
   "produced_by": null,
   "depends_on": ["https://w3id.org/awl/py/battery.procedure/procedure.i#7"]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#9",
   "_type": "Definition",
   "name": "i",
   "kind": "augmented",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14},
   "produced_by": null,
   "depends_on": ["https://w3id.org/awl/py/battery.procedure/procedure.i#7", "https://w3id.org/awl/py/battery.procedure/procedure.i#8"]
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix ns1: <https://w3id.org/awl/py/battery.params/ChargeParam#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<https://w3id.org/awl/py/battery.procedure/ChargeParam#3> a awl:Definition ;
    awl:kind "import" ;
    awl:name "ChargeParam" ;
    awl:producedBy "battery.params.ChargeParam" ;
    awl:scope "" ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/charge#1> a awl:Definition ;
    awl:kind "import" ;
    awl:name "charge" ;
    awl:producedBy "battery.device.charge" ;
    awl:scope "" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/measure#2> a awl:Definition ;
    awl:kind "import" ;
    awl:name "measure" ;
    awl:producedBy "battery.device.measure" ;
    awl:scope "" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.i#9> a awl:Definition ;
    awl:dependsOn <https://w3id.org/awl/py/battery.procedure/procedure.i#7>,
        <https://w3id.org/awl/py/battery.procedure/procedure.i#8> ;
    awl:kind "augmented" ;
    awl:name "i" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.report#6> a awl:Definition ;
    awl:dependsOn <https://w3id.org/awl/py/battery.procedure/Report#4> ;
    awl:kind "assign" ;
    awl:name "report" ;
    awl:producedBy "Report" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] .

<https://w3id.org/awl/py/battery.device/charge> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "charge" ;
    awl:module "battery.device" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] ;
    awl:symbol "charge" .

<https://w3id.org/awl/py/battery.device/measure> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "measure" ;
    awl:module "battery.device" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 22 ;
            awl:startLine 13 ] ;
    awl:symbol "measure" .

<https://w3id.org/awl/py/battery.params/ChargeParam> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "ChargeParam" ;
    awl:module "battery.params" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 46 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 15 ;
            awl:startLine 11 ] ;
    awl:symbol "ChargeParam" .

<https://w3id.org/awl/py/battery.procedure/Report#4> a awl:Definition ;
    awl:kind "import" ;
    awl:name "Report" ;
    awl:producedBy "battery.report.Report" ;
    awl:scope "" ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.cycles#5> a awl:Definition ;
    awl:kind "parameter" ;
    awl:name "cycles" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 25 ;
            awl:endLine 6 ;
            awl:file "procedure.py" ;
            awl:startCol 14 ;
            awl:startLine 6 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.i#8> a awl:Definition ;
    awl:dependsOn <https://w3id.org/awl/py/battery.procedure/procedure.i#7> ;
    awl:kind "augmented" ;
    awl:name "i" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#4> a awl:Assign,
        awl:Call,
        awl:Step ;
    awl:callee "Report" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#5> ;
    awl:order 0 ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] ;
    awl:targets [ awl:span [ awl:endCol 10 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 7 ] ;
            awl:var "report" ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.report/Report> ;
                    awl:span [ awl:endCol 19 ;
                            awl:endLine 7 ;
                            awl:file "procedure.py" ;
                            awl:startCol 13 ;
                            awl:startLine 7 ] ;
                    awl:var "Report" ] ;
            awl:span [ awl:endCol 21 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 7 ] ] .

<https://w3id.org/awl/py/battery.procedure/step#1> a awl:ImportFrom,
        awl:Step,
        awl:Unknown ;
    awl:level 0 ;
    awl:module "battery.device" ;
    awl:names "charge",
        "measure" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/step#2> ;
    awl:order 0 ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.report/Report> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "Report" ;
    awl:module "battery.report" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 13 ;
            awl:startLine 7 ] ;
    awl:symbol "Report" .

<https://w3id.org/awl/py/battery.procedure/procedure.step#5> a awl:Assign,
        awl:Call,
        awl:Step ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#6> ;
    awl:order 1 ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] ;
    awl:targets [ awl:span [ awl:endCol 5 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 8 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 0 ;
            awl:span [ awl:endCol 9 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 8 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#7> a awl:Call,
        awl:Step ;
    awl:argument ( [ a <https://w3id.org/awl/py/battery.params/ChargeParam> ;
                ns1:target_voltage 4.2e+00 ;
                awl:span [ awl:endCol 46 ;
                        awl:endLine 11 ;
                        awl:file "procedure.py" ;
                        awl:startCol 15 ;
                        awl:startLine 11 ] ] ) ;
    awl:callee "charge" ;
    awl:comment [ awl:span [ awl:endCol 54 ;
                    awl:endLine 10 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 10 ] ;
            awl:text "hold the cell at its target until it settles" ;
            awl:where "above" ] ;
    awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.device/charge> ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 11 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 11 ] ;
            awl:var "charge" ] ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ;
    awl:order 0 ;
    awl:parserTypeName "Expr" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#8> a awl:AugAssign,
        awl:Call,
        awl:Step ;
    awl:op "Add" ;
    awl:order 1 ;
    awl:parserTypeName "AugAssign" ;
    awl:repeat <https://w3id.org/awl/py/battery.procedure/procedure.step#6> ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] ;
    awl:target [ awl:span [ awl:endCol 9 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 12 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 1 ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 12 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#9> a awl:Assign,
        awl:Call,
        awl:Step ;
    awl:callee "measure" ;
    awl:comment [ awl:span [ awl:endCol 59 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 33 ;
                    awl:startLine 13 ] ;
            awl:text "what the cell held, once" ;
            awl:where "beside" ] ;
    awl:order 3 ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 13 ] ;
    awl:targets [ a awl:Attribute ;
            awl:attr "capacity" ;
            awl:span [ awl:endCol 19 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 13 ] ;
            awl:value [ awl:span [ awl:endCol 10 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 4 ;
                            awl:startLine 13 ] ;
                    awl:var "report" ] ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.device/measure> ;
                    awl:span [ awl:endCol 29 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 22 ;
                            awl:startLine 13 ] ;
                    awl:var "measure" ] ;
            awl:span [ awl:endCol 31 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 22 ;
                    awl:startLine 13 ] ] .

<https://w3id.org/awl/py/battery.procedure/step#2> a awl:ImportFrom,
        awl:Step,
        awl:Unknown ;
    awl:level 0 ;
    awl:module "battery.params" ;
    awl:names "ChargeParam" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/step#3> ;
    awl:order 1 ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/step#3> a awl:ImportFrom,
        awl:Step,
        awl:Unknown ;
    awl:level 0 ;
    awl:module "battery.report" ;
    awl:names "Report" ;
    awl:order 2 ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.i#7> a awl:Definition ;
    awl:kind "assign" ;
    awl:name "i" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#6> a awl:ControlStructure,
        awl:Step,
        awl:While ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#7> <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ) ;
    awl:condition [ a awl:Call ;
            awl:parserTypeName "Compare" ;
            awl:reads <https://w3id.org/awl/py/battery.procedure/procedure.cycles#5>,
                <https://w3id.org/awl/py/battery.procedure/procedure.i#7> ;
            awl:sourceText "i < cycles" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] ;
    awl:order 2 ;
    awl:parserTypeName "While" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 9 ] ;
    awl:test [ a awl:Compare ;
            awl:comparators [ awl:span [ awl:endCol 20 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 14 ;
                            awl:startLine 9 ] ;
                    awl:var "cycles" ] ;
            awl:left [ awl:span [ awl:endCol 11 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 10 ;
                            awl:startLine 9 ] ;
                    awl:var "i" ] ;
            awl:ops "Lt" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] ;
    awl:whenFalse <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ;
    awl:whenTrue <https://w3id.org/awl/py/battery.procedure/procedure.step#7> .

[] a awl:Module ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/step#1> <https://w3id.org/awl/py/battery.procedure/step#2> <https://w3id.org/awl/py/battery.procedure/step#3> [ a awl:FunctionDef ;
                awl:args [ awl:annotation [ awl:span [ awl:endCol 25 ;
                                        awl:endLine 6 ;
                                        awl:file "procedure.py" ;
                                        awl:startCol 22 ;
                                        awl:startLine 6 ] ;
                                awl:var "int" ] ;
                        awl:arg "cycles" ] ;
                awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#4> <https://w3id.org/awl/py/battery.procedure/procedure.step#5> <https://w3id.org/awl/py/battery.procedure/procedure.step#6> <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ) ;
                awl:name "procedure" ;
                awl:order 3 ;
                awl:returns [ awl:span [ awl:endCol 34 ;
                                awl:endLine 6 ;
                                awl:file "procedure.py" ;
                                awl:startCol 30 ;
                                awl:startLine 6 ] ] ;
                awl:span [ awl:endCol 31 ;
                        awl:endLine 13 ;
                        awl:file "procedure.py" ;
                        awl:startCol 0 ;
                        awl:startLine 6 ] ] ) .
graph TD
  n0(["i L12"])
  n1(["Call L13"])
  n2(["1 L12"])
  n3(["int L6"])
  n4(["ChargeParam L11<br>target_voltage 4.2"])
  n5(["Attribute L13"])
  n6(["report L7"])
  n7(["measure L13"])
  n8(["report L13"])
  n9(["0 L8"])
  n10(["Report L7"])
  n11(["procedure (FunctionDef) L6"])
  n12(["charge L11"])
  n13(["Compare L9"])
  n14(["i L8"])
  n15(["Compare (Call) L9"])
  n16(["Module"])
  n17(["Call L7"])
  n18(["i L9"])
  n19(["cycles L9"])
  n20["charge (Binding) L11"]
  n21["measure (Binding) L13"]
  n22["ChargeParam (Binding) L11"]
  n23["ChargeParam (Definition) L2 import"]
  n24["Report (Definition) L3 import"]
  n25["charge (Definition) L1 import"]
  n26["measure (Definition) L1 import"]
  n27["cycles (Definition) L6 parameter"]
  n28["i (Definition) L8 assign"]
  n29["i (Definition) L12 augmented #8"]
  n30["i (Definition) L12 augmented #9"]
  n31["report (Definition) L7 assign"]
  n32["Report (Assign, Call, Step) L7"]
  n33["Assign (Assign, Call, Step) L8"]
  n34["While (ControlStructure, Step, While) L9"]
  n35["charge (Call, Step) L11"]
  n36["AugAssign (AugAssign, Call, Step) L12"]
  n37["measure (Assign, Call, Step) L13"]
  n38["ImportFrom (ImportFrom, Step, Unknown) L1"]
  n39["ImportFrom (ImportFrom, Step, Unknown) L2"]
  n40["ImportFrom (ImportFrom, Step, Unknown) L3"]
  n41["Report (Binding) L7"]
  n1 -->|func| n7
  n4 -->|type| n22
  n5 -->|value| n8
  n7 -->|refersTo| n21
  n10 -->|refersTo| n41
  n11 -->|args| n3
  n11 -->|body| n32
  n11 -->|body| n33
  n11 -->|body| n34
  n11 -->|body| n37
  n12 -->|refersTo| n20
  n13 -->|comparators| n19
  n13 -->|left| n18
  n15 -->|reads| n27
  n15 -->|reads| n28
  n16 -->|body| n38
  n16 -->|body| n39
  n16 -->|body| n40
  n16 -->|body| n11
  n17 -->|func| n10
  n29 -->|dependsOn| n28
  n30 -->|dependsOn| n28
  n30 -->|dependsOn| n29
  n31 -->|dependsOn| n24
  n32 -->|next| n33
  n32 -->|targets| n6
  n32 -->|value| n17
  n33 -->|next| n34
  n33 -->|targets| n14
  n33 -->|value| n9
  n34 -->|body| n35
  n34 -->|body| n36
  n34 -->|condition| n15
  n34 -->|test| n13
  n34 -->|whenFalse| n37
  n34 -->|whenTrue| n35
  n35 -->|argument| n4
  n35 -->|func| n12
  n35 -->|next| n36
  n36 -->|repeat| n34
  n36 -->|target| n0
  n36 -->|value| n2
  n37 -->|targets| n5
  n37 -->|value| n1
  n38 -->|next| n39
  n39 -->|next| n40

Where does the value the loop test reads come from?

PREFIX awl: <https://w3id.org/awl/schema/>

SELECT ?definition ?kind WHERE {
  ?loop awl:condition [ awl:reads ?definition ] .
  ?definition awl:kind ?kind .
}
definition kind
py:battery.procedure/procedure.cycles#5 parameter
py:battery.procedure/procedure.i#7 assign

Everything

What the ast profile asks for, and what a query is actually run against. The typed member writes join the tree to the classes it constructs.

from battery.device import charge, measure
from battery.params import ChargeParam
from battery.report import Report


def procedure(cycles: int) -> None:
    report = Report()
    i = 0
    while i < cycles:
        # hold the cell at its target until it settles
        charge(ChargeParam(target_voltage=4.2))
        i += 1
    report.capacity = measure()  # what the cell held, once
{
 "@graph": [
  {
   "@type": "Module",
   "body": [
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
     "@type": "ImportFrom",
     "module": "battery.device",
     "names": ["charge", "measure"],
     "level": 0,
     "order": 0,
     "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
     "@type": "ImportFrom",
     "module": "battery.params",
     "names": ["ChargeParam"],
     "level": 0,
     "order": 1,
     "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38}
    },
    {
     "@id": "https://w3id.org/awl/py/battery.procedure/step#3",
     "@type": "ImportFrom",
     "module": "battery.report",
     "names": ["Report"],
     "level": 0,
     "order": 2,
     "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33}
    },
    {
     "@type": "FunctionDef",
     "name": "procedure",
     "args": [
      {
       "arg": "cycles",
       "annotation": {"var": "int", "span": {"file": "procedure.py", "start_line": 6, "start_col": 22, "end_line": 6, "end_col": 25}}
      }
     ],
     "body": [
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
       "@type": "Assign",
       "targets": [{"var": "report", "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 10}}],
       "value": {
        "@type": "Call",
        "func": {
         "var": "Report",
         "refers_to": {"@id": "https://w3id.org/awl/py/battery.report/Report"},
         "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 19}
        },
        "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21}
       },
       "order": 0,
       "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
       "@type": "Assign",
       "targets": [{"var": "i", "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 5}}],
       "value": {"literal": 0, "span": {"file": "procedure.py", "start_line": 8, "start_col": 8, "end_line": 8, "end_col": 9}},
       "order": 1,
       "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
       "@type": "While",
       "test": {
        "@type": "Compare",
        "left": {"var": "i", "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 11}},
        "ops": ["Lt"],
        "comparators": [{"var": "cycles", "span": {"file": "procedure.py", "start_line": 9, "start_col": 14, "end_line": 9, "end_col": 20}}],
        "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20}
       },
       "body": [
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
         "@type": "Call",
         "func": {
          "var": "charge",
          "refers_to": {"@id": "https://w3id.org/awl/py/battery.device/charge"},
          "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 14}
         },
         "args": [
          {
           "@type": ["ChargeParam"],
           "target_voltage": 4.2,
           "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46}
          }
         ],
         "order": 0,
         "comment": {
          "text": "hold the cell at its target until it settles",
          "where": "above",
          "span": {"file": "procedure.py", "start_line": 10, "start_col": 8, "end_line": 10, "end_col": 54}
         },
         "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47}
        },
        {
         "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
         "@type": "AugAssign",
         "target": {"var": "i", "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 9}},
         "op": "Add",
         "value": {"literal": 1, "span": {"file": "procedure.py", "start_line": 12, "start_col": 13, "end_line": 12, "end_col": 14}},
         "order": 1,
         "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14}
        }
       ],
       "order": 2,
       "span": {"file": "procedure.py", "start_line": 9, "start_col": 4, "end_line": 12, "end_col": 14}
      },
      {
       "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
       "@type": "Assign",
       "targets": [
        {
         "@type": "Attribute",
         "value": {"var": "report", "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 10}},
         "attr": "capacity",
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 19}
        }
       ],
       "value": {
        "@type": "Call",
        "func": {
         "var": "measure",
         "refers_to": {"@id": "https://w3id.org/awl/py/battery.device/measure"},
         "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 29}
        },
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31}
       },
       "order": 3,
       "comment": {
        "text": "what the cell held, once",
        "where": "beside",
        "span": {"file": "procedure.py", "start_line": 13, "start_col": 33, "end_line": 13, "end_col": 59}
       },
       "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 31}
      }
     ],
     "returns": {"literal": null, "span": {"file": "procedure.py", "start_line": 6, "start_col": 30, "end_line": 6, "end_col": 34}},
     "order": 3,
     "span": {"file": "procedure.py", "start_line": 6, "start_col": 0, "end_line": 13, "end_col": 31}
    }
   ]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/step#1",
   "_type": ["Step", "Unknown"],
   "parser_type_name": "ImportFrom",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/step#2"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/step#2",
   "_type": ["Step", "Unknown"],
   "parser_type_name": "ImportFrom",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/step#3"}]
  },
  {"@id": "https://w3id.org/awl/py/battery.procedure/step#3", "_type": ["Step", "Unknown"], "parser_type_name": "ImportFrom"},
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#4",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "callee": "Report",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#5",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6",
   "_type": ["Step", "ControlStructure"],
   "parser_type_name": "While",
   "condition": {
    "_type": "Call",
    "parser_type_name": "Compare",
    "source_text": "i < cycles",
    "span": {"file": "procedure.py", "start_line": 9, "start_col": 10, "end_line": 9, "end_col": 20},
    "reads": [
     {"@id": "https://w3id.org/awl/py/battery.procedure/procedure.cycles#5"},
     {"@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#7"}
    ]
   },
   "scope": "procedure",
   "when_true": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7"}],
   "when_false": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#7",
   "_type": ["Step", "Call"],
   "parser_type_name": "Expr",
   "callee": "charge",
   "scope": "procedure",
   "next": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#8",
   "_type": ["Step", "Call"],
   "parser_type_name": "AugAssign",
   "scope": "procedure",
   "repeat": [{"@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#6"}]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.step#9",
   "_type": ["Step", "Call"],
   "parser_type_name": "Assign",
   "callee": "measure",
   "scope": "procedure"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.report/Report",
   "_type": "Binding",
   "local_name": "Report",
   "span": {"file": "procedure.py", "start_line": 7, "start_col": 13, "end_line": 7, "end_col": 21},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.report",
   "symbol": "Report"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.device/charge",
   "_type": "Binding",
   "local_name": "charge",
   "span": {"file": "procedure.py", "start_line": 11, "start_col": 8, "end_line": 11, "end_col": 47},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.device",
   "symbol": "charge"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.params/ChargeParam",
   "_type": "Binding",
   "local_name": "ChargeParam",
   "span": {"file": "procedure.py", "start_line": 11, "start_col": 15, "end_line": 11, "end_col": 46},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.params",
   "symbol": "ChargeParam"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.device/measure",
   "_type": "Binding",
   "local_name": "measure",
   "span": {"file": "procedure.py", "start_line": 13, "start_col": 22, "end_line": 13, "end_col": 31},
   "confidence": "EXTRACTED",
   "scheme": "py",
   "module": "battery.device",
   "symbol": "measure"
  },
  {
   "_type": "Write",
   "path": "report.capacity",
   "span": {"file": "procedure.py", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 31},
   "written_by": "measure",
   "confidence": "INFERRED",
   "root_type": "https://w3id.org/awl/py/battery.report/Report",
   "member_of": "https://w3id.org/awl/py/battery.report/Report",
   "member": "https://w3id.org/awl/py/battery.report/Report/capacity",
   "member_path": "Report.capacity",
   "range": "https://w3id.org/awl/py/battery.report/Capacity",
   "range_name": "Capacity"
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/charge#1",
   "_type": "Definition",
   "name": "charge",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42},
   "produced_by": "battery.device.charge",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/measure#2",
   "_type": "Definition",
   "name": "measure",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 1, "start_col": 0, "end_line": 1, "end_col": 42},
   "produced_by": "battery.device.measure",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/ChargeParam#3",
   "_type": "Definition",
   "name": "ChargeParam",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 2, "start_col": 0, "end_line": 2, "end_col": 38},
   "produced_by": "battery.params.ChargeParam",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/Report#4",
   "_type": "Definition",
   "name": "Report",
   "kind": "import",
   "scope": "",
   "span": {"file": "procedure.py", "start_line": 3, "start_col": 0, "end_line": 3, "end_col": 33},
   "produced_by": "battery.report.Report",
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.cycles#5",
   "_type": "Definition",
   "name": "cycles",
   "kind": "parameter",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 6, "start_col": 14, "end_line": 6, "end_col": 25},
   "produced_by": null,
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.report#6",
   "_type": "Definition",
   "name": "report",
   "kind": "assign",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 7, "start_col": 4, "end_line": 7, "end_col": 21},
   "produced_by": "Report",
   "depends_on": ["https://w3id.org/awl/py/battery.procedure/Report#4"]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#7",
   "_type": "Definition",
   "name": "i",
   "kind": "assign",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 8, "start_col": 4, "end_line": 8, "end_col": 9},
   "produced_by": null,
   "depends_on": []
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#8",
   "_type": "Definition",
   "name": "i",
   "kind": "augmented",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14},
   "produced_by": null,
   "depends_on": ["https://w3id.org/awl/py/battery.procedure/procedure.i#7"]
  },
  {
   "@id": "https://w3id.org/awl/py/battery.procedure/procedure.i#9",
   "_type": "Definition",
   "name": "i",
   "kind": "augmented",
   "scope": "procedure",
   "span": {"file": "procedure.py", "start_line": 12, "start_col": 8, "end_line": 12, "end_col": 14},
   "produced_by": null,
   "depends_on": ["https://w3id.org/awl/py/battery.procedure/procedure.i#7", "https://w3id.org/awl/py/battery.procedure/procedure.i#8"]
  }
 ]
}
@prefix awl: <https://w3id.org/awl/schema/> .
@prefix ns1: <https://w3id.org/awl/py/battery.params/ChargeParam#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<https://w3id.org/awl/py/battery.procedure/ChargeParam#3> a awl:Definition ;
    awl:kind "import" ;
    awl:name "ChargeParam" ;
    awl:producedBy "battery.params.ChargeParam" ;
    awl:scope "" ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/charge#1> a awl:Definition ;
    awl:kind "import" ;
    awl:name "charge" ;
    awl:producedBy "battery.device.charge" ;
    awl:scope "" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/measure#2> a awl:Definition ;
    awl:kind "import" ;
    awl:name "measure" ;
    awl:producedBy "battery.device.measure" ;
    awl:scope "" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.i#9> a awl:Definition ;
    awl:dependsOn <https://w3id.org/awl/py/battery.procedure/procedure.i#7>,
        <https://w3id.org/awl/py/battery.procedure/procedure.i#8> ;
    awl:kind "augmented" ;
    awl:name "i" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.report#6> a awl:Definition ;
    awl:dependsOn <https://w3id.org/awl/py/battery.procedure/Report#4> ;
    awl:kind "assign" ;
    awl:name "report" ;
    awl:producedBy "Report" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] .

<https://w3id.org/awl/py/battery.device/charge> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "charge" ;
    awl:module "battery.device" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] ;
    awl:symbol "charge" .

<https://w3id.org/awl/py/battery.device/measure> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "measure" ;
    awl:module "battery.device" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 22 ;
            awl:startLine 13 ] ;
    awl:symbol "measure" .

<https://w3id.org/awl/py/battery.params/ChargeParam> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "ChargeParam" ;
    awl:module "battery.params" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 46 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 15 ;
            awl:startLine 11 ] ;
    awl:symbol "ChargeParam" .

<https://w3id.org/awl/py/battery.procedure/Report#4> a awl:Definition ;
    awl:kind "import" ;
    awl:name "Report" ;
    awl:producedBy "battery.report.Report" ;
    awl:scope "" ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.cycles#5> a awl:Definition ;
    awl:kind "parameter" ;
    awl:name "cycles" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 25 ;
            awl:endLine 6 ;
            awl:file "procedure.py" ;
            awl:startCol 14 ;
            awl:startLine 6 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.i#8> a awl:Definition ;
    awl:dependsOn <https://w3id.org/awl/py/battery.procedure/procedure.i#7> ;
    awl:kind "augmented" ;
    awl:name "i" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#4> a awl:Assign,
        awl:Call,
        awl:Step ;
    awl:callee "Report" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#5> ;
    awl:order 0 ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 7 ] ;
    awl:targets [ awl:span [ awl:endCol 10 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 7 ] ;
            awl:var "report" ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.report/Report> ;
                    awl:span [ awl:endCol 19 ;
                            awl:endLine 7 ;
                            awl:file "procedure.py" ;
                            awl:startCol 13 ;
                            awl:startLine 7 ] ;
                    awl:var "Report" ] ;
            awl:span [ awl:endCol 21 ;
                    awl:endLine 7 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 7 ] ] .

<https://w3id.org/awl/py/battery.procedure/step#1> a awl:ImportFrom,
        awl:Step,
        awl:Unknown ;
    awl:level 0 ;
    awl:module "battery.device" ;
    awl:names "charge",
        "measure" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/step#2> ;
    awl:order 0 ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 42 ;
            awl:endLine 1 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 1 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#5> a awl:Assign,
        awl:Call,
        awl:Step ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#6> ;
    awl:order 1 ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] ;
    awl:targets [ awl:span [ awl:endCol 5 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 8 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 0 ;
            awl:span [ awl:endCol 9 ;
                    awl:endLine 8 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 8 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#7> a awl:Call,
        awl:Step ;
    awl:argument ( [ a <https://w3id.org/awl/py/battery.params/ChargeParam> ;
                ns1:target_voltage 4.2e+00 ;
                awl:span [ awl:endCol 46 ;
                        awl:endLine 11 ;
                        awl:file "procedure.py" ;
                        awl:startCol 15 ;
                        awl:startLine 11 ] ] ) ;
    awl:callee "charge" ;
    awl:comment [ awl:span [ awl:endCol 54 ;
                    awl:endLine 10 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 10 ] ;
            awl:text "hold the cell at its target until it settles" ;
            awl:where "above" ] ;
    awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.device/charge> ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 11 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 11 ] ;
            awl:var "charge" ] ;
    awl:next <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ;
    awl:order 0 ;
    awl:parserTypeName "Expr" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 47 ;
            awl:endLine 11 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 11 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#8> a awl:AugAssign,
        awl:Call,
        awl:Step ;
    awl:op "Add" ;
    awl:order 1 ;
    awl:parserTypeName "AugAssign" ;
    awl:repeat <https://w3id.org/awl/py/battery.procedure/procedure.step#6> ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 8 ;
            awl:startLine 12 ] ;
    awl:target [ awl:span [ awl:endCol 9 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 8 ;
                    awl:startLine 12 ] ;
            awl:var "i" ] ;
    awl:value [ awl:literal 1 ;
            awl:span [ awl:endCol 14 ;
                    awl:endLine 12 ;
                    awl:file "procedure.py" ;
                    awl:startCol 13 ;
                    awl:startLine 12 ] ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#9> a awl:Assign,
        awl:Call,
        awl:Step ;
    awl:callee "measure" ;
    awl:comment [ awl:span [ awl:endCol 59 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 33 ;
                    awl:startLine 13 ] ;
            awl:text "what the cell held, once" ;
            awl:where "beside" ] ;
    awl:order 3 ;
    awl:parserTypeName "Assign" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 13 ] ;
    awl:targets [ a awl:Attribute ;
            awl:attr "capacity" ;
            awl:span [ awl:endCol 19 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 4 ;
                    awl:startLine 13 ] ;
            awl:value [ awl:span [ awl:endCol 10 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 4 ;
                            awl:startLine 13 ] ;
                    awl:var "report" ] ] ;
    awl:value [ a awl:Call ;
            awl:func [ awl:refersTo <https://w3id.org/awl/py/battery.device/measure> ;
                    awl:span [ awl:endCol 29 ;
                            awl:endLine 13 ;
                            awl:file "procedure.py" ;
                            awl:startCol 22 ;
                            awl:startLine 13 ] ;
                    awl:var "measure" ] ;
            awl:span [ awl:endCol 31 ;
                    awl:endLine 13 ;
                    awl:file "procedure.py" ;
                    awl:startCol 22 ;
                    awl:startLine 13 ] ] .

<https://w3id.org/awl/py/battery.procedure/step#2> a awl:ImportFrom,
        awl:Step,
        awl:Unknown ;
    awl:level 0 ;
    awl:module "battery.params" ;
    awl:names "ChargeParam" ;
    awl:next <https://w3id.org/awl/py/battery.procedure/step#3> ;
    awl:order 1 ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 38 ;
            awl:endLine 2 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 2 ] .

<https://w3id.org/awl/py/battery.procedure/step#3> a awl:ImportFrom,
        awl:Step,
        awl:Unknown ;
    awl:level 0 ;
    awl:module "battery.report" ;
    awl:names "Report" ;
    awl:order 2 ;
    awl:parserTypeName "ImportFrom" ;
    awl:span [ awl:endCol 33 ;
            awl:endLine 3 ;
            awl:file "procedure.py" ;
            awl:startCol 0 ;
            awl:startLine 3 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.i#7> a awl:Definition ;
    awl:kind "assign" ;
    awl:name "i" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 9 ;
            awl:endLine 8 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 8 ] .

<https://w3id.org/awl/py/battery.procedure/procedure.step#6> a awl:ControlStructure,
        awl:Step,
        awl:While ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#7> <https://w3id.org/awl/py/battery.procedure/procedure.step#8> ) ;
    awl:condition [ a awl:Call ;
            awl:parserTypeName "Compare" ;
            awl:reads <https://w3id.org/awl/py/battery.procedure/procedure.cycles#5>,
                <https://w3id.org/awl/py/battery.procedure/procedure.i#7> ;
            awl:sourceText "i < cycles" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] ;
    awl:order 2 ;
    awl:parserTypeName "While" ;
    awl:scope "procedure" ;
    awl:span [ awl:endCol 14 ;
            awl:endLine 12 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 9 ] ;
    awl:test [ a awl:Compare ;
            awl:comparators [ awl:span [ awl:endCol 20 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 14 ;
                            awl:startLine 9 ] ;
                    awl:var "cycles" ] ;
            awl:left [ awl:span [ awl:endCol 11 ;
                            awl:endLine 9 ;
                            awl:file "procedure.py" ;
                            awl:startCol 10 ;
                            awl:startLine 9 ] ;
                    awl:var "i" ] ;
            awl:ops "Lt" ;
            awl:span [ awl:endCol 20 ;
                    awl:endLine 9 ;
                    awl:file "procedure.py" ;
                    awl:startCol 10 ;
                    awl:startLine 9 ] ] ;
    awl:whenFalse <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ;
    awl:whenTrue <https://w3id.org/awl/py/battery.procedure/procedure.step#7> .

<https://w3id.org/awl/py/battery.report/Report> a awl:Binding ;
    awl:confidence "EXTRACTED" ;
    awl:localName "Report" ;
    awl:module "battery.report" ;
    awl:scheme "py" ;
    awl:span [ awl:endCol 21 ;
            awl:endLine 7 ;
            awl:file "procedure.py" ;
            awl:startCol 13 ;
            awl:startLine 7 ] ;
    awl:symbol "Report" .

[] a awl:Write ;
    awl:confidence "INFERRED" ;
    awl:member <https://w3id.org/awl/py/battery.report/Report/capacity> ;
    awl:memberOf <https://w3id.org/awl/py/battery.report/Report> ;
    awl:memberPath "Report.capacity" ;
    awl:path "report.capacity" ;
    awl:range <https://w3id.org/awl/py/battery.report/Capacity> ;
    awl:rangeName "Capacity" ;
    awl:rootType <https://w3id.org/awl/py/battery.report/Report> ;
    awl:span [ awl:endCol 31 ;
            awl:endLine 13 ;
            awl:file "procedure.py" ;
            awl:startCol 4 ;
            awl:startLine 13 ] ;
    awl:writtenBy "measure" .

[] a awl:Module ;
    awl:body ( <https://w3id.org/awl/py/battery.procedure/step#1> <https://w3id.org/awl/py/battery.procedure/step#2> <https://w3id.org/awl/py/battery.procedure/step#3> [ a awl:FunctionDef ;
                awl:args [ awl:annotation [ awl:span [ awl:endCol 25 ;
                                        awl:endLine 6 ;
                                        awl:file "procedure.py" ;
                                        awl:startCol 22 ;
                                        awl:startLine 6 ] ;
                                awl:var "int" ] ;
                        awl:arg "cycles" ] ;
                awl:body ( <https://w3id.org/awl/py/battery.procedure/procedure.step#4> <https://w3id.org/awl/py/battery.procedure/procedure.step#5> <https://w3id.org/awl/py/battery.procedure/procedure.step#6> <https://w3id.org/awl/py/battery.procedure/procedure.step#9> ) ;
                awl:name "procedure" ;
                awl:order 3 ;
                awl:returns [ awl:span [ awl:endCol 34 ;
                                awl:endLine 6 ;
                                awl:file "procedure.py" ;
                                awl:startCol 30 ;
                                awl:startLine 6 ] ] ;
                awl:span [ awl:endCol 31 ;
                        awl:endLine 13 ;
                        awl:file "procedure.py" ;
                        awl:startCol 0 ;
                        awl:startLine 6 ] ] ) .
graph TD
  n0(["i L12"])
  n1(["Call L13"])
  n2(["1 L12"])
  n3(["int L6"])
  n4(["ChargeParam L11<br>target_voltage 4.2"])
  n5(["Attribute L13"])
  n6(["report L7"])
  n7(["measure L13"])
  n8(["report L13"])
  n9(["0 L8"])
  n10(["Report L7"])
  n11(["procedure (FunctionDef) L6"])
  n12(["charge L11"])
  n13(["Compare L9"])
  n14(["i L8"])
  n15(["Compare (Call) L9"])
  n16(["Write L13"])
  n17(["Module"])
  n18(["Call L7"])
  n19(["i L9"])
  n20(["cycles L9"])
  n21["charge (Binding) L11"]
  n22["measure (Binding) L13"]
  n23["ChargeParam (Binding) L11"]
  n24["ChargeParam (Definition) L2 import"]
  n25["Report (Definition) L3 import"]
  n26["charge (Definition) L1 import"]
  n27["measure (Definition) L1 import"]
  n28["cycles (Definition) L6 parameter"]
  n29["i (Definition) L8 assign"]
  n30["i (Definition) L12 augmented #8"]
  n31["i (Definition) L12 augmented #9"]
  n32["report (Definition) L7 assign"]
  n33["Report (Assign, Call, Step) L7"]
  n34["Assign (Assign, Call, Step) L8"]
  n35["While (ControlStructure, Step, While) L9"]
  n36["charge (Call, Step) L11"]
  n37["AugAssign (AugAssign, Call, Step) L12"]
  n38["measure (Assign, Call, Step) L13"]
  n39["ImportFrom (ImportFrom, Step, Unknown) L1"]
  n40["ImportFrom (ImportFrom, Step, Unknown) L2"]
  n41["ImportFrom (ImportFrom, Step, Unknown) L3"]
  n42["Capacity"]
  n43["Report (Binding) L7"]
  n44["capacity"]
  n1 -->|func| n7
  n4 -->|type| n23
  n5 -->|value| n8
  n7 -->|refersTo| n22
  n10 -->|refersTo| n43
  n11 -->|args| n3
  n11 -->|body| n33
  n11 -->|body| n34
  n11 -->|body| n35
  n11 -->|body| n38
  n12 -->|refersTo| n21
  n13 -->|comparators| n20
  n13 -->|left| n19
  n15 -->|reads| n28
  n15 -->|reads| n29
  n16 -->|member| n44
  n16 -->|memberOf| n43
  n16 -->|range| n42
  n16 -->|rootType| n43
  n17 -->|body| n39
  n17 -->|body| n40
  n17 -->|body| n41
  n17 -->|body| n11
  n18 -->|func| n10
  n30 -->|dependsOn| n29
  n31 -->|dependsOn| n29
  n31 -->|dependsOn| n30
  n32 -->|dependsOn| n25
  n33 -->|next| n34
  n33 -->|targets| n6
  n33 -->|value| n18
  n34 -->|next| n35
  n34 -->|targets| n14
  n34 -->|value| n9
  n35 -->|body| n36
  n35 -->|body| n37
  n35 -->|condition| n15
  n35 -->|test| n13
  n35 -->|whenFalse| n38
  n35 -->|whenTrue| n36
  n36 -->|argument| n4
  n36 -->|func| n12
  n36 -->|next| n37
  n37 -->|repeat| n35
  n37 -->|target| n0
  n37 -->|value| n2
  n38 -->|targets| n5
  n38 -->|value| n1
  n39 -->|next| n40
  n40 -->|next| n41

What does this procedure produce, and from which step?

PREFIX awl: <https://w3id.org/awl/schema/>

SELECT ?member ?range ?line WHERE {
  ?write awl:memberPath ?member ; awl:range ?range ;
         awl:span [ awl:startLine ?line ] .
}
member range line
Report.capacity py:battery.report/Capacity 13