<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"Segoe UI Emoji";
        panose-1:2 11 5 2 4 2 4 2 2 3;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
@font-face
        {font-family:"Lucida Console";
        panose-1:2 11 6 9 4 5 4 2 2 4;}
@font-face
        {font-family:Monaco;
        panose-1:0 0 0 0 0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0in;
        font-size:10.0pt;
        font-family:"Courier New";}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0in;
        margin-right:0in;
        margin-bottom:0in;
        margin-left:.5in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.apple-converted-space
        {mso-style-name:apple-converted-space;}
p.m6872490181044312902msolistparagraph, li.m6872490181044312902msolistparagraph, div.m6872490181044312902msolistparagraph
        {mso-style-name:m6872490181044312902msolistparagraph;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:Consolas;}
span.m6872490181044312902ansi-red-fg
        {mso-style-name:m6872490181044312902ansi-red-fg;}
span.m6872490181044312902apple-converted-space
        {mso-style-name:m6872490181044312902apple-converted-space;}
span.m6872490181044312902pre
        {mso-style-name:m6872490181044312902pre;}
span.m6872490181044312902ansi-green-fg
        {mso-style-name:m6872490181044312902ansi-green-fg;}
span.m6872490181044312902ansi-cyan-fg
        {mso-style-name:m6872490181044312902ansi-cyan-fg;}
span.m6872490181044312902ansi-blue-fg
        {mso-style-name:m6872490181044312902ansi-blue-fg;}
span.m6872490181044312902ansi-green-intense-fg
        {mso-style-name:m6872490181044312902ansi-green-intense-fg;}
span.EmailStyle31
        {mso-style-type:personal;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
span.EmailStyle33
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:44334282;
        mso-list-template-ids:1222800458;}
@list l0:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l1
        {mso-list-id:173617909;
        mso-list-template-ids:1344452514;}
@list l1:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l1:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l1:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l1:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l1:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l1:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l1:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l1:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l1:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l2
        {mso-list-id:201555294;
        mso-list-type:hybrid;
        mso-list-template-ids:-109178040 1588656122 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l2:level1
        {mso-level-start-at:0;
        mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-fareast-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
@list l2:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l2:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l2:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l2:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l2:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l2:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l2:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l2:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l3
        {mso-list-id:283314456;
        mso-list-type:hybrid;
        mso-list-template-ids:-1269294894 -1823569808 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l3:level1
        {mso-level-start-at:0;
        mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-fareast-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
@list l3:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l3:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l3:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l3:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l3:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l3:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l3:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l3:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l4
        {mso-list-id:347416234;
        mso-list-template-ids:-561226526;}
@list l4:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l4:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l4:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l4:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l4:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l4:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l4:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l4:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l4:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l5
        {mso-list-id:510067619;
        mso-list-type:hybrid;
        mso-list-template-ids:-1113430842 -1544113720 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l5:level1
        {mso-level-start-at:5;
        mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-fareast-font-family:"Times New Roman";
        mso-bidi-font-family:Calibri;}
@list l5:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l5:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l5:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l5:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l5:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l5:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l5:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l5:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l6
        {mso-list-id:520898356;
        mso-list-template-ids:-1655426366;}
@list l6:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l6:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l6:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l6:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l6:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l6:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l6:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l6:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l6:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l7
        {mso-list-id:529729403;
        mso-list-template-ids:1749470322;}
@list l7:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l7:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l7:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l7:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l7:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l7:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l7:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l7:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l7:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l8
        {mso-list-id:725758471;
        mso-list-template-ids:145407228;}
@list l8:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l8:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l8:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l8:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l8:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l8:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l8:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l8:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l8:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l9
        {mso-list-id:779377054;
        mso-list-template-ids:-1338744124;}
@list l9:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l9:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l9:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l9:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l9:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l9:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l9:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l9:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l9:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l10
        {mso-list-id:946699864;
        mso-list-template-ids:-1733762776;}
@list l10:level1
        {mso-level-start-at:7;
        mso-level-number-format:alpha-lower;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l10:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l10:level3
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l10:level4
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l10:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l10:level6
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l10:level7
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l10:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l10:level9
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l11
        {mso-list-id:1044790600;
        mso-list-template-ids:1943280672;}
@list l11:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l11:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l11:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l11:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l11:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l11:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l11:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l11:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l11:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l12
        {mso-list-id:1078094115;
        mso-list-type:hybrid;
        mso-list-template-ids:1198676472 -745867588 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l12:level1
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:.25in;
        text-indent:-.25in;
        font-family:"Times New Roman",serif;
        mso-ascii-font-family:Calibri;
        mso-fareast-font-family:Calibri;
        mso-hansi-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
@list l12:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:.75in;
        text-indent:-.25in;}
@list l12:level3
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        margin-left:1.25in;
        text-indent:-9.0pt;}
@list l12:level4
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:1.75in;
        text-indent:-.25in;}
@list l12:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:2.25in;
        text-indent:-.25in;}
@list l12:level6
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        margin-left:2.75in;
        text-indent:-9.0pt;}
@list l12:level7
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:3.25in;
        text-indent:-.25in;}
@list l12:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:3.75in;
        text-indent:-.25in;}
@list l12:level9
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        margin-left:4.25in;
        text-indent:-9.0pt;}
@list l13
        {mso-list-id:1089697267;
        mso-list-template-ids:-1674013036;}
@list l13:level1
        {mso-level-start-at:8;
        mso-level-number-format:alpha-lower;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l13:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l13:level3
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l13:level4
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l13:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l13:level6
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l13:level7
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l13:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l13:level9
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l14
        {mso-list-id:1109817031;
        mso-list-template-ids:450922104;}
@list l14:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l14:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l14:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l14:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l14:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l14:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l14:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l14:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l14:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l15
        {mso-list-id:1209491143;
        mso-list-type:hybrid;
        mso-list-template-ids:1159654446 -1868428998 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l15:level1
        {mso-level-start-at:0;
        mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-fareast-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
@list l15:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l15:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l15:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l15:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l15:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l15:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l15:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l15:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l16
        {mso-list-id:1227767876;
        mso-list-template-ids:-2126988200;}
@list l16:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l16:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l16:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l16:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l16:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l16:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l16:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l16:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l16:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l17
        {mso-list-id:1495494162;
        mso-list-type:hybrid;
        mso-list-template-ids:-156838070 1318387700 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l17:level1
        {mso-level-start-at:0;
        mso-level-number-format:bullet;
        mso-level-text:"";
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-fareast-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
@list l17:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l17:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l17:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l17:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l17:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l17:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l17:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l17:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l18
        {mso-list-id:1521238840;
        mso-list-template-ids:-7038806;}
@list l18:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l18:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l18:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l18:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l18:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l18:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l18:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l18:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l18:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l19
        {mso-list-id:1985161534;
        mso-list-template-ids:-254655308;}
@list l19:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l19:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l19:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l19:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l19:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l19:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l19:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l19:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l19:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l20
        {mso-list-id:2007129988;
        mso-list-type:hybrid;
        mso-list-template-ids:1153971954 -2096314688 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l20:level1
        {mso-level-start-at:0;
        mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-fareast-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
@list l20:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l20:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l20:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l20:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l20:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l20:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l20:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l20:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l21
        {mso-list-id:2019303914;
        mso-list-template-ids:-1728519340;}
@list l21:level1
        {mso-level-start-at:6;
        mso-level-number-format:alpha-lower;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l21:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l21:level3
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l21:level4
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l21:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l21:level6
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l21:level7
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l21:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l21:level9
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l22
        {mso-list-id:2045981496;
        mso-list-template-ids:1638700110;}
@list l22:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l22:level2
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l22:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l22:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l22:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l22:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l22:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l22:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l22:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l23
        {mso-list-id:2071146736;
        mso-list-template-ids:1716702564;}
@list l23:level1
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l23:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l23:level3
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l23:level4
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l23:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l23:level6
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l23:level7
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l23:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l23:level9
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link=blue vlink=purple style='word-wrap:break-word'><div class=WordSection1><p class=MsoNormal>Thanks for super feedback, sounds promising.  <o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><ol style='margin-top:0in' start=1 type=1><li class=MsoListParagraph style='margin-left:-.25in;mso-list:l12 level1 lfo23'>Fixed capitalization in autognerated <span style='font-size:10.0pt;font-family:"Courier New"'>__init__.py</span>  file.<o:p></o:p></li></ol><p class=MsoListParagraph style='margin-left:.25in'><o:p> </o:p></p><ol style='margin-top:0in' start=2 type=1><li class=MsoListParagraph style='margin-left:-.25in;mso-list:l12 level1 lfo23'>Got the dot! “from .x3d import *”<o:p></o:p></li></ol><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Inspectable at<o:p></o:p></p><ul style='margin-top:0in' type=disc><li class=MsoListParagraph style='margin-left:0in;mso-list:l5 level1 lfo24'>https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/stylesheets/python/__init__.py<o:p></o:p></li></ul><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Full details on relative imports at<o:p></o:p></p><ul style='margin-top:0in' type=disc><li class=MsoListParagraph style='margin-left:0in;mso-list:l3 level1 lfo22'>https://docs.python.org/3/reference/import.html#package-relative-imports<o:p></o:p></li></ul><p class=MsoNormal><o:p> </o:p></p><ol style='margin-top:0in' start=3 type=1><li class=MsoListParagraph style='margin-left:-.25in;mso-list:l12 level1 lfo23'>Added NumpyExample.py to build tests, works fine<o:p></o:p></li></ol><p class=MsoNormal><o:p> </o:p></p><ul style='margin-top:0in' type=disc><li class=MsoListParagraph style='margin-left:0in;mso-list:l3 level1 lfo22'>https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/stylesheets/python/examples/NumpyExample.py<o:p></o:p></li></ul><p class=MsoListParagraph style='margin-left:.25in'><o:p> </o:p></p><ol style='margin-top:0in' start=4 type=1><li class=MsoListParagraph style='margin-left:-.25in;mso-list:l12 level1 lfo23'>Rechecked setup.py according to<o:p></o:p></li></ol><ul style='margin-top:0in' type=disc><li class=MsoListParagraph style='margin-left:0in;mso-list:l3 level1 lfo22'>https://docs.python.org/3/distutils/setupscript.html<o:p></o:p></li></ul><div><p class=MsoNormal><o:p> </o:p></p><ol style='margin-top:0in' start=5 type=1><li class=MsoListParagraph style='margin-left:-.25in;mso-list:l12 level1 lfo23'>Bad news, still no joy.  Following “pip install x3d” and hiding PYTHONPATH, the PyPi version installed via pip still fails, now saying:<o:p></o:p></li></ol><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console";color:#00BF00'>IT160907-UWALPP+brutzman@IT160907-UWALPP </span><span style='font-size:9.0pt;font-family:"Lucida Console";color:#BFBF00'>/cygdrive/c/x3d-code/www.web3d.org/x3d/content/examples/X3dForWebAuthors/Chapter02GeometryPrimitives<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>$ python BoxExample.py<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>Traceback (most recent call last):<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>  File "C:\x3d-code\www.web3d.org\x3d\content\examples\X3dForWebAuthors\Chapter02GeometryPrimitives\BoxExample.py", line 23, in <module><o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>    import x3d<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>ModuleNotFoundError: No module named 'x3d'<o:p></o:p></span></p><p class=MsoNormal><o:p> </o:p></p><ol style='margin-top:0in' start=6 type=1><li class=MsoListParagraph style='margin-left:-.25in;mso-list:l12 level1 lfo23'>Here is what it looks like with same local x3d.py directory found in PYTHONPATH<o:p></o:p></li></ol><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console";color:#00BF00'>IT160907-UWALPP+brutzman@IT160907-UWALPP </span><span style='font-size:9.0pt;font-family:"Lucida Console";color:#BFBF00'>/cygdrive/c/x3d-code/www.web3d.org/x3d/content/examples/X3dForWebAuthors/Chapter02GeometryPrimitives<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>$ python BoxExample.py<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>x3d.py package 4.0.60 loaded, have fun with X3D Graphics!<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>Python-to-XML well-formed XML document  test of XML output complete<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>Python-to-XML X3D 3.3 schema validation test of XML output complete<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>Python-to-VRML export of VRML output successful<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>Python-to-JSON export of JSON output successful (under development)<o:p></o:p></span></p><p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;font-family:"Lucida Console"'>python x3d.py load and self-test complete for BoxExample.py<o:p></o:p></span></p><p class=MsoNormal><o:p> </o:p></p><ol style='margin-top:0in' start=7 type=1><li class=MsoListParagraph style='margin-left:-.25in;mso-list:l12 level1 lfo23'>And so, am still stuck.  Arggh.  Further review welcome.  I have checked in everything, now including the build artifacts.<o:p></o:p></li></ol><p class=MsoNormal><o:p> </o:p></p><ul style='margin-top:0in' type=disc><li class=MsoListParagraph style='margin-left:0in;mso-list:l3 level1 lfo22'>https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/stylesheets/python<o:p></o:p></li><li class=MsoListParagraph style='margin-left:0in;mso-list:l3 level1 lfo22'>https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/stylesheets/python/x3d.egg-info<o:p></o:p></li></ul><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>all the best, Don<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>-- <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Don Brutzman  Naval Postgraduate School, Code USW/Br        brutzman@nps.edu<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA    +1.831.656.2149<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>X3D graphics, virtual worlds, Navy robotics https://</span> <span style='font-size:10.0pt;font-family:"Courier New"'>faculty.nps.edu/brutzman<o:p></o:p></span></p></div><p class=MsoNormal><o:p> </o:p></p><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal><b>From:</b> vmarchetti@kshell.com <vmarchetti@kshell.com> <br><b>Sent:</b> Tuesday, March 1, 2022 9:46 AM<br><b>To:</b> Brutzman, Donald (Don) (CIV) <brutzman@nps.edu>; X3D-Public <x3d-public@web3d.org><br><b>Cc:</b> John Carlson <yottzumm@gmail.com>; Peitso, Loren (CIV) <lepeitso@nps.edu>; Hans Moritz Guenther <hgunther@mit.edu><br><b>Subject:</b> Re: [x3d-public] x3d.py package: Some feedback and suggestion for improvement; tuples and lists; updated x3d.py<o:p></o:p></p></div></div><div><p class=MsoNormal>I have taken an additional look at this. <o:p></o:p></p><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>1. In the file x3d/__init__.py , for the pypi installation, a Python list is declared with name of __all__ , this is a magic name in the Python import system and is intended to be a list of strings, matching the names of Python elements in a module. At the version 4.0.51 this list is no longer consistent with the contents of the x3d.py file, in particular the string 'accessTypeChoices' is in the __all__ list, but there is no Python content of that name in x3d.py (there is a different capitalization version, ACCESSTYPECHOICES . Python is case-sensitve throughout.<o:p></o:p></p></div><div><p class=MsoNormal>This breaks some of the import statements, so as a temporary fixed I renamed the __all__ variable so it is inert and harmless. The other fix would be to update __all__<o:p></o:p></p></div><div><p class=MsoListParagraph style='margin-left:0in'><o:p> </o:p></p><ul style='margin-top:0in' type=disc><li class=MsoListParagraph style='margin-left:0in;mso-list:l15 level1 lfo21'> Have updated autogeneration rule for __all_ to include matching capitalization for these enumerations.<o:p></o:p></li></ul><ul style='margin-top:0in' type=disc><li class=MsoListParagraph style='margin-left:0in;mso-list:l17 level1 lfo18'><o:p> </o:p></li></ul></div><div><p class=MsoNormal>2. With the __all__ variable removed as discussed above, I added this statement as the last line of the x3d/__init__.py file:<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>############## added ######<o:p></o:p></p></div><div><p class=MsoNormal>from .x3d import *<o:p></o:p></p></div><div><p class=MsoNormal>############## end added ###<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>With that change, I was able to run the NumpyExample.py script using either of the import statements at the top of the script:<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>from x3d import *<o:p></o:p></p></div><div><p class=MsoNormal>OR <o:p></o:p></p></div><div><p class=MsoNormal>from x3d.x3d import *<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>My confirmation is on a system with only the Pypi installation of the x3d package, and no site-specific modification of the Python package search functions.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>This fix, or something very close to it, was suggested by Moritz Guenther in one of his emails to the Consortium or mailing list.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>For Python-heads : In the statement "from .x3d import *' the period before x3d is crucial, it activates the concept of Python relative import : see <a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.python.org%2F3%2Freference%2Fimport.html&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610573878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=omk23QAef2xroumVFYzUYNdCSRgUa0fLOVDjUsjB7Pk%3D&reserved=0">https://docs.python.org/3/reference/import.html</a><o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Vince Marchetti<o:p></o:p></p></div><div><div><p class=MsoNormal><br><br><o:p></o:p></p><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div><p class=MsoNormal>On Mar 1, 2022, at 10:02 AM, Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu">brutzman@nps.edu</a>> wrote:<o:p></o:p></p></div><p class=MsoNormal><o:p> </o:p></p><div><div><p class=MsoNormal>Our goal is to make this widely repeatable without problems, used by anyone.  So we must get the simplest of cases sorted out first.<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>The pypi distribution of x3d.py does not behave the same as someone’s local copy of x3d.py package, presumably because of the __init__.py provided with it or possibly some other configuration file.  Sleuthing and testing continue.<o:p></o:p></p></div><div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'> </span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>all the best, Don</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>--<span class=apple-converted-space> </span></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Don Brutzman  Naval Postgraduate School, Code USW/Br       <span class=apple-converted-space> </span><a href="mailto:brutzman@nps.edu"><span style='color:purple'>brutzman@nps.edu</span></a></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA    +1.831.656.2149</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>X3D graphics, virtual worlds, Navy robotics https://</span><span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'><a href="http://faculty.nps.edu/brutzman"><span style='color:purple'>faculty.nps.edu/brutzman</span></a></span><o:p></o:p></p></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><div><p class=MsoNormal><b>From:</b><span class=apple-converted-space> </span>John Carlson <<a href="mailto:yottzumm@gmail.com"><span style='color:purple'>yottzumm@gmail.com</span></a>><span class=apple-converted-space> </span><br><b>Sent:</b><span class=apple-converted-space> </span>Monday, February 28, 2022 8:47 PM<br><b>To:</b><span class=apple-converted-space> </span>Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu"><span style='color:purple'>brutzman@nps.edu</span></a>><br><b>Cc:</b><span class=apple-converted-space> </span>Hans Moritz Guenther <<a href="mailto:hgunther@mit.edu"><span style='color:purple'>hgunther@mit.edu</span></a>>; Peitso, Loren (CIV) <<a href="mailto:lepeitso@nps.edu"><span style='color:purple'>lepeitso@nps.edu</span></a>>; X3D Public Mailing List (<a href="mailto:x3d-public@web3d.org"><span style='color:purple'>x3d-public@web3d.org</span></a>) <<a href="mailto:x3d-public@web3d.org"><span style='color:purple'>x3d-public@web3d.org</span></a>><br><b>Subject:</b><span class=apple-converted-space> </span>Re: [x3d-public] x3d.py package: Some feedback and suggestion for improvement; tuples and lists; updated x3d.py<o:p></o:p></p></div></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><div><div><p class=MsoNormal>Ok, Don.   I mostly just copy x3d.py to my source folder and set PYTHONPATH.  Maybe you could try in a conda or python virtual environment?<o:p></o:p></p></div></div><div><div><p class=MsoNormal> <o:p></o:p></p></div></div><div><div><p class=MsoNormal> <o:p></o:p></p></div><div><div><div><p class=MsoNormal>On Mon, Feb 28, 2022 at 10:44 PM Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu"><span style='color:purple'>brutzman@nps.edu</span></a>> wrote:<o:p></o:p></p></div></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt'><div><div><div><p class=MsoNormal>Have tried a few solutions to getting things working without having the double x3d.x3d import statement.  Unfortunately still not working.<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Latest stable build remains<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l22 level1 lfo1'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpypi.org%2Fproject%2Fx3d%2F4.0.51&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610573878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=7e3tTYAtr63mTy6BtSNYauvvr%2BFJtgZ2fF6XnK7G6Pc%3D&reserved=0" target="_blank"><span style='color:purple'>https://pypi.org/project/x3d/4.0.51</span></a><o:p></o:p></li></ul></div></div><div><div><div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'> </span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>all the best, Don</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>--<span class=apple-converted-space> </span></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Don Brutzman  Naval Postgraduate School, Code USW/Br       <span class=apple-converted-space> </span><a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA    +1.831.656.2149</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>X3D graphics, virtual worlds, Navy robotics https://</span><span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'><a href="http://faculty.nps.edu/brutzman" target="_blank"><span style='color:purple'>faculty.nps.edu/brutzman</span></a></span><o:p></o:p></p></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><div><p class=MsoNormal><b>From:</b><span class=apple-converted-space> </span>Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a>><span class=apple-converted-space> </span><br><b>Sent:</b><span class=apple-converted-space> </span>Wednesday, February 23, 2022 7:30 AM<br><b>To:</b><span class=apple-converted-space> </span>X3D Public Mailing List (<a href="mailto:x3d-public@web3d.org" target="_blank"><span style='color:purple'>x3d-public@web3d.org</span></a>) <<a href="mailto:x3d-public@web3d.org" target="_blank"><span style='color:purple'>x3d-public@web3d.org</span></a>><br><b>Cc:</b><span class=apple-converted-space> </span>rlentz <<a href="mailto:rlentz@gmail.com" target="_blank"><span style='color:purple'>rlentz@gmail.com</span></a>>; Vince Marchetti <<a href="mailto:vmarchetti@kshell.com" target="_blank"><span style='color:purple'>vmarchetti@kshell.com</span></a>>; Mike McCann <<a href="mailto:mccann@mbari.org" target="_blank"><span style='color:purple'>mccann@mbari.org</span></a>>; Peitso, Loren (CIV) <<a href="mailto:lepeitso@nps.edu" target="_blank"><span style='color:purple'>lepeitso@nps.edu</span></a>>; Hans Moritz Guenther <<a href="mailto:hgunther@mit.edu" target="_blank"><span style='color:purple'>hgunther@mit.edu</span></a>>; Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a>><br><b>Subject:</b><span class=apple-converted-space> </span>RE: x3d.py package: Some feedback and suggestion for improvement; tuples and lists; updated x3d.py<o:p></o:p></p></div></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Have released another build of x3d.py (aka X3DJSAIL), now version 4.0.51.<o:p></o:p></p></div><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l8 level1 lfo2'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpypi.org%2Fproject%2Fx3d&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610573878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=wx49U15gxIkHs0EZ7f8O%2F1GRofDyhebuxAj4ARgE2Xg%3D&reserved=0" target="_blank"><span style='color:purple'>https://pypi.org/project/x3d</span></a><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l8 level1 lfo2'><a href="https://www.web3d.org/x3d/stylesheets/python/python.html" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/python.html</span></a><o:p></o:p></li></ul><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Updated features include:<o:p></o:p></p></div><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l19 level1 lfo3'>Override (and report) when a contained MetadataSet (or other Metadata*) node has incorrect containerField, providing extra care since default values changed in X3D4.  Similar checks are provided in X3dTidy stylesheet.<o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l19 level1 lfo3'>When a conversion error to XML (.x3d output file) occurs, only print out 7 lines of result file containing the error (instead of the whole file).<o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l19 level1 lfo3'>Proper handling of typed values contained by <field> or <fieldValue> initializations for Script nodes and prototypes.<o:p></o:p></li></ul><div style='border:none;border-bottom:double windowtext 2.25pt;padding:0in 0in 1.0pt 0in'><div><p class=MsoNormal> <o:p></o:p></p></div></div><div><p class=MsoNormal>create python:<o:p></o:p></p></div><div><p class=MsoNormal>C:\x3d-code\<a href="http://www.web3d.org/" target="_blank"><span style='color:purple'>www.web3d.org</span></a>\x3d\content\examples\X3dForWebAuthors/Chapter14Prototypes//TextStringPrototype.x3d processing with X3dToPython stylesheet...<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>C:\x3d-code\<a href="http://www.web3d.org/" target="_blank"><span style='color:purple'>www.web3d.org</span></a>\x3d\content\examples\X3dForWebAuthors/Chapter14Prototypes//TextStringPrototype.py self-validation tests...<o:p></o:p></p></div><div><p class=MsoNormal>validate python:<o:p></o:p></p></div><div><p class=MsoNormal>x3d.py package loaded, have fun with X3D Graphics!<o:p></o:p></p></div><div><p class=MsoNormal>Python-to-XML well-formed XML document  test of XML output complete<o:p></o:p></p></div><div><p class=MsoNormal>Python-to-XML X3D 3.3 schema validation test of XML output complete<o:p></o:p></p></div><div><p class=MsoNormal>Python-to-VRML export of VRML output successful<o:p></o:p></p></div><div><p class=MsoNormal>Python-to-JSON export of JSON output successful (under development)<o:p></o:p></p></div><div><p class=MsoNormal>python x3d.py load and self-test complete for TextStringPrototype.py<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l0 level1 lfo4'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fx3dgraphics.com%2Fexamples%2FX3dForWebAuthors%2FChapter14Prototypes%2FTextStringPrototypeIndex.html&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610573878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=lFr2RUn33JQZl%2FyXdRyTtXYYsiLTdQLU9aXpurtVDp0%3D&reserved=0" target="_blank"><span style='color:purple'>https://x3dgraphics.com/examples/X3dForWebAuthors/Chapter14Prototypes/TextStringPrototypeIndex.html</span></a><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l0 level1 lfo4'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fx3dgraphics.com%2Fexamples%2FX3dForWebAuthors%2FChapter14Prototypes%2FTextStringPrototype.py&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610573878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=UoaQmUDo4iJhBj5BgNfp%2F6xYYjZ93vX8bUsXhRFTmak%3D&reserved=0" target="_blank"><span style='color:purple'>https://x3dgraphics.com/examples/X3dForWebAuthors/Chapter14Prototypes/TextStringPrototype.py</span></a><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l0 level1 lfo4'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fx3dgraphics.com%2Fexamples%2FX3dForWebAuthors%2FChapter14Prototypes%2FTextStringPrototype.x3d&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610573878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=jG18pUgyiMcwf3xLawh24TJoHU1RV7mYWxlLfaQzPSI%3D&reserved=0" target="_blank"><span style='color:purple'>https://x3dgraphics.com/examples/X3dForWebAuthors/Chapter14Prototypes/TextStringPrototype.x3d</span></a><o:p></o:p></li></ul><div style='border:none;border-bottom:double windowtext 2.25pt;padding:0in 0in 1.0pt 0in'><div><p class=MsoNormal> <o:p></o:p></p></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>The regression tests are running very cleanly, when processing the X3D Examples archives a handful of errors in field initializations were detected and now few exceptions are reported.  Perhaps the only recurring exceptions are when some of our extremely large scans are encountered, too big for my laptop to published.<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l1 level1 lfo5'><a href="https://www.web3d.org/x3d/content/examples/build.python.all.log.txt" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/content/examples/build.python.all.log.txt</span></a><o:p></o:p></li></ul><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Also upgraded the Saxon xslt engine to version 11.2 of open-source home edition (HE), to good effect.<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l16 level1 lfo6'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.saxonica.com%2Fhtml%2Fdocumentation11%2Fabout&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610573878%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=DV7rsjxGdCSSgPlTBnv%2F%2FcyMS%2BnrwmgoINz3dqQYuTc%3D&reserved=0" target="_blank"><span style='color:purple'>https://www.saxonica.com/html/documentation11/about</span></a><o:p></o:p></li></ul><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Have fun with X3D Python!   8)<o:p></o:p></p></div><div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'> </span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>all the best, Don</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>--<span class=apple-converted-space> </span></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Don Brutzman  Naval Postgraduate School, Code USW/Br       <span class=apple-converted-space> </span><a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA    +1.831.656.2149</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>X3D graphics, virtual worlds, Navy robotics https://</span><span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'><a href="http://faculty.nps.edu/brutzman" target="_blank"><span style='color:purple'>faculty.nps.edu/brutzman</span></a></span><o:p></o:p></p></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><div><p class=MsoNormal><b>From:</b><span class=apple-converted-space> </span>Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a>><span class=apple-converted-space> </span><br><b>Sent:</b><span class=apple-converted-space> </span>Monday, February 21, 2022 9:41 AM<br><b>To:</b><span class=apple-converted-space> </span>Hans Moritz Guenther <<a href="mailto:hgunther@mit.edu" target="_blank"><span style='color:purple'>hgunther@mit.edu</span></a>>; X3D Public Mailing List (<a href="mailto:x3d-public@web3d.org" target="_blank"><span style='color:purple'>x3d-public@web3d.org</span></a>) <<a href="mailto:x3d-public@web3d.org" target="_blank"><span style='color:purple'>x3d-public@web3d.org</span></a>><br><b>Cc:</b><span class=apple-converted-space> </span>rlentz <<a href="mailto:rlentz@gmail.com" target="_blank"><span style='color:purple'>rlentz@gmail.com</span></a>>; Vince Marchetti <<a href="mailto:vmarchetti@kshell.com" target="_blank"><span style='color:purple'>vmarchetti@kshell.com</span></a>>; Mike McCann <<a href="mailto:mccann@mbari.org" target="_blank"><span style='color:purple'>mccann@mbari.org</span></a>>; Peitso, Loren (CIV) <<a href="mailto:lepeitso@nps.edu" target="_blank"><span style='color:purple'>lepeitso@nps.edu</span></a>>; Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a>><br><b>Subject:</b><span class=apple-converted-space> </span>RE: x3d.py package: Some feedback and suggestion for improvement; tuples and lists; updated x3d.py<o:p></o:p></p></div></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Hello all python programmers.  Another x3d.py release is available.  Have performed a complete refactoring of field type setters as well as corresponding isValid* and assertValid* methods.  The field types now perform value validation whenever setting, and duck typing is preserved wherever possible up and down within the X3D field types.  Now published to PyPi with corresponding unit tests complete.<o:p></o:p></p></div><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l7 level1 lfo7'>x3d 4.0.50<span class=apple-converted-space> </span><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l7 level1 lfo7'><span style='font-family:"Courier New"'>pip install x3d==4.0.50</span><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l7 level1 lfo7'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpypi.org%2Fproject%2Fx3d%2F4.0.50&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=yEACKYmvcqPb3PZ3gjzcAdezLTMPh%2BoY6dRreSwpry8%3D&reserved=0" target="_blank"><span style='color:purple'>https://pypi.org/project/x3d/4.0.50</span></a><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l7 level1 lfo7'>X3D Examples Archive regression tests, several post-test improvements are being added:<o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l7 level1 lfo7'><a href="https://www.web3d.org/x3d/content/examples/build.python.all.log.txt" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/content/examples/build.python.all.log.txt</span></a><o:p></o:p></li></ul><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Once again a large number of smoke tests have been added, confirming it is indeed a good way to check new functionality.<o:p></o:p></p></div><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l14 level1 lfo8'><a href="https://www.web3d.org/x3d/stylesheets/python/examples/PythonX3dSmokeTests.py" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/examples/PythonX3dSmokeTests.py</span></a><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l14 level1 lfo8'><a href="https://www.web3d.org/x3d/stylesheets/python/build.examples.log.txt" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/build.examples.log.txt</span></a><o:p></o:p></li></ul><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>I’ve looked at numpy a little, but there are many types.  We’re ready to consider utility methods.  Up until now, I have hesitated to offer plain-array support for data types since that might easily break tuple checks.<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Example(s) showing common use cases for X3D with numpy would be helpful, TIA.<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>all the best, Don</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>--<span class=apple-converted-space> </span></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Don Brutzman  Naval Postgraduate School, Code USW/Br       <span class=apple-converted-space> </span><a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA    +1.831.656.2149</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>X3D graphics, virtual worlds, Navy robotics https://</span><span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'><a href="http://faculty.nps.edu/brutzman" target="_blank"><span style='color:purple'>faculty.nps.edu/brutzman</span></a></span><o:p></o:p></p></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><div><p class=MsoNormal><b>From:</b><span class=apple-converted-space> </span>Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a>><span class=apple-converted-space> </span><br><b>Sent:</b><span class=apple-converted-space> </span>Sunday, February 13, 2022 11:08 PM<br><b>To:</b><span class=apple-converted-space> </span>Hans Moritz Guenther <<a href="mailto:hgunther@mit.edu" target="_blank"><span style='color:purple'>hgunther@mit.edu</span></a>>; Peitso, Loren (CIV) <<a href="mailto:lepeitso@nps.edu" target="_blank"><span style='color:purple'>lepeitso@nps.edu</span></a>><br><b>Cc:</b><span class=apple-converted-space> </span>rlentz <<a href="mailto:rlentz@gmail.com" target="_blank"><span style='color:purple'>rlentz@gmail.com</span></a>>; Vince Marchetti <<a href="mailto:vmarchetti@kshell.com" target="_blank"><span style='color:purple'>vmarchetti@kshell.com</span></a>>; Mike McCann <<a href="mailto:mccann@mbari.org" target="_blank"><span style='color:purple'>mccann@mbari.org</span></a>>; X3D Public Mailing List (<a href="mailto:x3d-public@web3d.org" target="_blank"><span style='color:purple'>x3d-public@web3d.org</span></a>) <<a href="mailto:x3d-public@web3d.org" target="_blank"><span style='color:purple'>x3d-public@web3d.org</span></a>>; Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a>><br><b>Subject:</b><span class=apple-converted-space> </span>RE: x3d.py package: Some feedback and suggestion for improvement; tuples and lists; updated x3d.py<o:p></o:p></p></div></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>I have updated x3d.py to include  several points of progress.<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><ol start=1 type=a><li class=m6872490181044312902msolistparagraph style='mso-list:l23 level1 lfo9'>REGEX_PYTHON (perturbated from REGEX_XML) for all types.  Validation of each X3D-typed python value now includes regex checking.<o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l23 level1 lfo9'>The standard python library ‘re’ for regexes is now imported by x3d.py<o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l23 level1 lfo9'>In X3D XML Schemas and X3DUOM, made regex occurrence (\s) consistent throughout as \s<o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l23 level1 lfo9'>Strings are now allowed as validatable values for some simple types.  More work needed for list and array combinations.<o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l23 level1 lfo9'>Documentation and tests:<o:p></o:p></li></ol><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l4 level1 lfo10'>Python X3D Package x3d.py<o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l4 level1 lfo10'>“The x3d.py Python X3D Package supports programmers with Python interfaces and objects for standards-based X3D programming, all as open source.”<o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l4 level1 lfo10'><a href="https://www.web3d.org/x3d/stylesheets/python/python.html" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/python.html</span></a><o:p></o:p></li></ul><div><p class=MsoNormal> <o:p></o:p></p></div><ol start=6 type=a><li class=m6872490181044312902msolistparagraph style='mso-list:l21 level1 lfo11'>A large number of smoke tests have been added, this is indeed a good way to check new functionality.<o:p></o:p></li></ol><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l18 level1 lfo12'><a href="https://www.web3d.org/x3d/stylesheets/python/examples/PythonX3dSmokeTests.py" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/examples/PythonX3dSmokeTests.py</span></a><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l18 level1 lfo12'><a href="https://www.web3d.org/x3d/stylesheets/python/build.examples.log.txt" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/build.examples.log.txt</span></a><o:p></o:p></li></ul><p class=m6872490181044312902msolistparagraph style='margin-left:.25in'> <o:p></o:p></p><ol start=7 type=a><li class=m6872490181044312902msolistparagraph style='mso-list:l10 level1 lfo13'>Have added section on Data Types to X3D Python page.<o:p></o:p></li></ol><div><p class=MsoNormal> <o:p></o:p></p></div><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l11 level1 lfo14'><a href="https://www.web3d.org/x3d/stylesheets/python/python.html#DataTypes" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/python.html#DataTypes</span></a><o:p></o:p></li></ul><div style='border:none;border-bottom:solid windowtext 1.5pt;padding:0in 0in 1.0pt 0in'><div><p class=MsoNormal> <o:p></o:p></p></div></div><div><p class=MsoNormal><b><span style='font-size:12.0pt'><a href="https://www.web3d.org/x3d/stylesheets/python/python.html#DataTypes" target="_blank"><span style='font-family:"Segoe UI Emoji",sans-serif;color:purple'>🔖</span></a><span class=apple-converted-space> </span>Data Types<span class=apple-converted-space> </span></span></b><o:p></o:p></p></div><div><p class=MsoNormal>An important aspect of Python ease of programming is<span class=apple-converted-space> </span><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FDuck_typing&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=vNED01kmiH0jq0k80r8NUjBvhfMxJHfXNH5eJeehp8Y%3D&reserved=0" target="_blank"><span style='color:purple'>duck typing</span></a>: If it looks like a duck and walks like a duck and quacks like a duck, then it must be a duck.<span class=apple-converted-space> </span><o:p></o:p></p></div><div><p class=MsoNormal><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.python.org%2F3%2Fglossary.html%23term-duck-typing&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=DgZm0pmpsxc0mRUJl40dW7c4fDw24BnEx0NLQEpb8K8%3D&reserved=0" target="_blank"><span style='color:purple'>Python duck typing</span></a><span class=apple-converted-space> </span>describes how well-designed code improves its flexibility by allowing polymorphic substitution (i.e.<span class=apple-converted-space> </span><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FParametric_polymorphism&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=vhtpnrl6REzxXdO%2BXa743Ob0VeNASOCzjAA0ipqZ8NM%3D&reserved=0" target="_blank"><span style='color:purple'>parametric polymorphism</span></a>).<span class=apple-converted-space> </span><o:p></o:p></p></div><div><p class=MsoNormal>X3D has strictly defined<span class=apple-converted-space> </span><a href="https://www.web3d.org/specifications/X3Dv4Draft/ISO-IEC19775-1v4-CD1/Part01/fieldTypes.html" target="_blank" title="X3D Architecture specification, field types"><span style='color:purple'>field types</span></a><span class=apple-converted-space> </span>for every field of every node in the standard. This means that all values can be statically checked when defining a model, leading to high-quality model files. Further it is an error to provide an incorrectly typed value at run time, i.e. an SFString cannot be directly used as a numeric value. This approach precludes a wide range of errors that can occur in other languages. Details on each possible X3D type can be found at<span class=apple-converted-space> </span><a href="https://www.web3d.org/x3d/content/X3dTooltips.html#type" target="_blank"><span style='color:purple'>X3D Tooltips: types</span></a>.<span class=apple-converted-space> </span><o:p></o:p></p></div><div><p class=MsoNormal>Strict typing checks are included when building X3D classes and assigning values to fields, for all X3D types. This strictness for input data prevents<span class=apple-converted-space> </span><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FGarbage_in%2C_garbage_out&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=FpbUU06pR%2Fon85yPbMSp5R%2BFaAaoyeudoEeiJSqQ0TI%3D&reserved=0" target="_blank"><span style='color:purple'>Garbage in, garbage out</span></a><span class=apple-converted-space> </span>pathologies when creating X3D models.<span class=apple-converted-space> </span><o:p></o:p></p></div><div><p class=MsoNormal><a href="https://www.web3d.org/specifications/X3dRegularExpressions.html" target="_blank"><span style='color:purple'>X3D regular expression (regex)</span></a><span class=apple-converted-space> </span>checking is applied to result values. Each type class includes string constants for<span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'>REGEX_PYTHON</span><span class=apple-converted-space> </span>and<span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'>REGEX_PYTHON</span><span class=apple-converted-space> </span>patterns.<span class=apple-converted-space> </span><o:p></o:p></p></div><div><p class=MsoNormal>Python authors can confirm data validity and take further advantage of available type-checking methods, such as the following:<span class=apple-converted-space> </span><o:p></o:p></p></div><ul style='margin-top:0in' type=disc><li class=MsoNormal style='mso-list:l6 level1 lfo15'>Checks<span class=apple-converted-space> </span><i>value</i><span class=apple-converted-space> </span>expression and reports results as boolean:<span class=apple-converted-space> </span><br><span style='font-size:10.0pt;font-family:"Courier New"'>isValidSFBool(<i>value</i>)</span>,<span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'>isValidSFVec3f(<i>value</i>)</span>,<span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'>isValidMFRotation(<i>value</i>)</span>, etc.<span class=apple-converted-space> </span><o:p></o:p></li><li class=MsoNormal style='mso-list:l6 level1 lfo15'>Checks<span class=apple-converted-space> </span><i>value</i><span class=apple-converted-space> </span>expression and assets valid results, or else Fails and throws traceback:<span class=apple-converted-space> </span><br><span style='font-size:10.0pt;font-family:"Courier New"'>assertValidSFBool(<i>value</i>)</span>,<span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'>assertValidSFVec3f(<i>value</i>)</span>,<span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'>assertValidMFRotation(<i>value</i>)</span>, etc.<span class=apple-converted-space> </span><o:p></o:p></li></ul><div style='border:none;border-bottom:solid windowtext 1.5pt;padding:0in 0in 1.0pt 0in'><div><p class=MsoNormal>The<span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'>x3d.py python</span><span class=apple-converted-space> </span>package strives to support duck typing of unambiguous values while preserving strict X3D validation of all inputs. Example tests for each case can be found in<span class=apple-converted-space> </span><a href="https://www.web3d.org/x3d/stylesheets/python/examples/PythonX3dSmokeTests.py" target="_blank"><span style='color:purple'>examples/PythonX3dSmokeTests.py</span></a><span class=apple-converted-space> </span>with corresponding outputs shown in<span class=apple-converted-space> </span><a href="https://www.web3d.org/x3d/stylesheets/python/build.examples.log.txt" target="_blank"><span style='color:purple'>build.examples.log.txt</span></a><o:p></o:p></p></div></div><ol start=8 type=a><li class=m6872490181044312902msolistparagraph style='mso-list:l13 level1 lfo16'>Update available for installation/refresh<o:p></o:p></li></ol><ul type=disc><li class=m6872490181044312902msolistparagraph style='mso-list:l9 level1 lfo17'>x3d 4.0.49<span class=apple-converted-space> </span><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l9 level1 lfo17'><span style='font-family:"Courier New"'>pip install x3d==4.0.49</span><o:p></o:p></li><li class=m6872490181044312902msolistparagraph style='mso-list:l9 level1 lfo17'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpypi.org%2Fproject%2Fx3d%2F4.0.49&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=OgyoL%2FMwwlJ1qKSZOkKq9Q9tL6ViCoL0LO48UYz7ljk%3D&reserved=0" target="_blank"><span style='color:purple'>https://pypi.org/project/x3d/4.0.49</span></a><o:p></o:p></li></ul><div><p class=MsoNormal>g. It would be helpful to have a simple example program contributed that uses both x3d.py and numpy packages, this will doubtless inform current development future testing.<o:p></o:p></p></div><div><p class=MsoNormal>Unit tests appear to be passing, I hope these changes are indeed improvements.  Updated test reports welcome.<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Have fun with X3D Python!  8)<o:p></o:p></p></div><div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'> </span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>all the best, Don</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>--<span class=apple-converted-space> </span></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Don Brutzman  Naval Postgraduate School, Code USW/Br       <span class=apple-converted-space> </span><a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA    +1.831.656.2149</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>X3D graphics, virtual worlds, Navy robotics https://</span><span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'><a href="http://faculty.nps.edu/brutzman" target="_blank"><span style='color:purple'>faculty.nps.edu/brutzman</span></a></span><o:p></o:p></p></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><div><p class=MsoNormal><b>From:</b><span class=apple-converted-space> </span>Brutzman, Donald (Don) (CIV)<span class=apple-converted-space> </span><br><b>Sent:</b><span class=apple-converted-space> </span>Saturday, February 12, 2022 5:50 PM<br><b>To:</b><span class=apple-converted-space> </span>Hans Moritz Guenther <<a href="mailto:hgunther@mit.edu" target="_blank"><span style='color:purple'>hgunther@mit.edu</span></a>>; Peitso, Loren (CIV) <<a href="mailto:lepeitso@nps.edu" target="_blank"><span style='color:purple'>lepeitso@nps.edu</span></a>><br><b>Cc:</b><span class=apple-converted-space> </span>rlentz <<a href="mailto:rlentz@gmail.com" target="_blank"><span style='color:purple'>rlentz@gmail.com</span></a>>; Vince Marchetti <<a href="mailto:vmarchetti@kshell.com" target="_blank"><span style='color:purple'>vmarchetti@kshell.com</span></a>>; Mike McCann <<a href="mailto:mccann@mbari.org" target="_blank"><span style='color:purple'>mccann@mbari.org</span></a>>; X3D Public Mailing List (<a href="mailto:x3d-public@web3d.org" target="_blank"><span style='color:purple'>x3d-public@web3d.org</span></a>) <<a href="mailto:x3d-public@web3d.org" target="_blank"><span style='color:purple'>x3d-public@web3d.org</span></a>>;<span class=apple-converted-space> </span><a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a><br><b>Subject:</b><span class=apple-converted-space> </span>RE: x3d.py package: Some feedback and suggestion for improvement; tuples and lists<o:p></o:p></p></div></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>[Cc: x3d-public list, all design discussions are open and archived]<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>Splitting out one issue at a time (see subject line please)<o:p></o:p></p></div><div><p class=MsoNormal> <o:p></o:p></p></div><div style='border:none;border-bottom:solid windowtext 1.5pt;padding:0in 0in 1.0pt 0in'><div><p class=MsoNormal>Moritz wrote:<o:p></o:p></p></div></div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>This works:<span class=apple-converted-space> </span><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.Coordinate(point=[[0, 0, 0], (0, 1, 0), (1, 1, 0)])<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>This fails:<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.Coordinate(point=([0, 0, 0], (0, 1, 0), (1, 1, 0)))<o:p></o:p></span></p><pre><span class=m6872490181044312902ansi-red-fg>X3DTypeError</span>: ([0, 0, 0], (0, 1, 0), (1, 1, 0)), type=<class 'tuple'> is not a valid Python list for MFVec3f<o:p></o:p></pre><div><p class=MsoNormal> <o:p></o:p></p></div><pre><span style='font-family:"Calibri",sans-serif'>Why not allow a tuple instead of a list here? The inner coordinates can be either tuples or lists.</span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><div style='border:none;border-bottom:solid windowtext 1.5pt;padding:0in 0in 1.0pt 0in'><pre><span style='font-family:"Calibri",sans-serif'>I don't understand what that typechecking is good for here.</span><o:p></o:p></pre></div><pre> <o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'>Background: X3D types include strongly typed tuples (Single Field Vector, SFVec* types) and ordered lists of those same types (Multiple Field Vector, MFVec* types)</span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><pre style='margin-left:.5in'><span style='font-family:Symbol'>·</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>        </span><span style='font-family:"Calibri",sans-serif'>X3D4 Architecture, clause 5 Field type reference</span><o:p></o:p></pre><pre style='margin-left:.5in'><span style='font-family:Symbol'>·</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>        </span><span style='font-family:"Calibri",sans-serif'><a href="https://www.web3d.org/specifications/X3Dv4Draft/ISO-IEC19775-1v4-CD1/Part01/fieldTypes.html" target="_blank"><span style='color:purple'>https://www.web3d.org/specifications/X3Dv4Draft/ISO-IEC19775-1v4-CD1/Part01/fieldTypes.html</span></a></span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'>further explained at</span><o:p></o:p></pre><pre style='margin-left:.5in'><span style='font-family:Symbol'>·</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>        </span><span style='font-family:"Calibri",sans-serif'>X3D Tooltips, Type definitions</span><o:p></o:p></pre><pre style='margin-left:.5in'><span style='font-family:Symbol'>·</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>        </span><span style='font-family:"Calibri",sans-serif'><a href="https://www.web3d.org/x3d/content/X3dTooltips.html#type" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/content/X3dTooltips.html#type</span></a></span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'>Not yet described in the documentation, but evident in the code, is the design decision to use python tuples for SFVec types, and python lists for MFVec types.</span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'>This remains the most logical alignment with Python data structures.</span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'>Glad to see your test case provoked an understandable error!  Indeed </span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'>The intent of strictness is to avoid run-time problems that can easily arise from lackadaisical treatment of arrays.  Something like your example might look obvious in an example composed of numeric data, but might be much less clear if variables are used.</span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'>Am further concerned that if mixed combinations of values are allowed, then isolation of errors within long lists might not be possible/practical if error messages remain as terse as above (or, conversely, if error messages are immensely complex).</span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'>If is conceivable we might find some cases where we can safely add support.  For example, creating a new SFVec3f([1,2,3]) might be allowable.</span><o:p></o:p></pre><pre> <o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'>Am thinking we should be careful on this one.  Defining some simple acceptable variations that we might add to the Smoke Tests would be a good next step.</span><o:p></o:p></pre><pre><span style='font-family:"Calibri",sans-serif'> </span><o:p></o:p></pre><pre style='margin-left:.5in'><span style='font-family:Symbol'>·</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>        </span><span style='font-family:"Calibri",sans-serif'><a href="https://www.web3d.org/x3d/stylesheets/python/examples/PythonX3dSmokeTests.py" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/examples/PythonX3dSmokeTests.py</span></a></span><o:p></o:p></pre><pre style='margin-left:.5in'><span style='font-family:Symbol'>·</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>        </span><span style='font-family:"Calibri",sans-serif'><a href="https://www.web3d.org/x3d/stylesheets/python/build.examples.log.txt" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/build.examples.log.txt</span></a></span><o:p></o:p></pre><pre> <o:p></o:p></pre><div><p class=MsoNormal><span style='font-size:10.0pt'>The place to put any relaxations will be in the type classes themselves, e.g. SFVec3f and MFVec3f etc.</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'> </span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>all the best, Don</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>--<span class=apple-converted-space> </span></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Don Brutzman  Naval Postgraduate School, Code USW/Br       <span class=apple-converted-space> </span><a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a></span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA    +1.831.656.2149</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Courier New"'>X3D graphics, virtual worlds, Navy robotics https://</span><span class=apple-converted-space> </span><span style='font-size:10.0pt;font-family:"Courier New"'><a href="http://faculty.nps.edu/brutzman" target="_blank"><span style='color:purple'>faculty.nps.edu/brutzman</span></a></span><o:p></o:p></p></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><div><p class=MsoNormal><b>From:</b><span class=apple-converted-space> </span>Hans Moritz Guenther <<a href="mailto:hgunther@mit.edu" target="_blank"><span style='color:purple'>hgunther@mit.edu</span></a>><span class=apple-converted-space> </span><br><b>Sent:</b><span class=apple-converted-space> </span>Friday, February 11, 2022 7:45 PM<br><b>To:</b><span class=apple-converted-space> </span>Peitso, Loren (CIV) <<a href="mailto:lepeitso@nps.edu" target="_blank"><span style='color:purple'>lepeitso@nps.edu</span></a>><br><b>Cc:</b><span class=apple-converted-space> </span>Brutzman, Donald (Don) (CIV) <<a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'>brutzman@nps.edu</span></a>>; rlentz <<a href="mailto:rlentz@gmail.com" target="_blank"><span style='color:purple'>rlentz@gmail.com</span></a>>; Vince Marchetti <<a href="mailto:vmarchetti@kshell.com" target="_blank"><span style='color:purple'>vmarchetti@kshell.com</span></a>>; Mike McCann <<a href="mailto:mccann@mbari.org" target="_blank"><span style='color:purple'>mccann@mbari.org</span></a>><br><b>Subject:</b><span class=apple-converted-space> </span>Re: x3d.py package: Some feedback and suggestion for improvement<o:p></o:p></p></div></div></div><div><div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal>On 2/11/22 8:47 PM, Peitso, Loren (CIV) wrote:<o:p></o:p></p></div></div><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div><p class=MsoNormal><span style='font-size:14.0pt'>Hans,</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:14.0pt'>I have had a chat with Don and we are in full agreement that your described use case is important and would be quite useful for widening the usefulness of the x3d package.  Consideration for expanding usability is to not break anything (obviously), remain Pythonic, and not add additional code constructs/constraints that require consideration of architectural changes every time something needs adding or updating.   I'll propose a couple solutions by issue-raised and we can discuss debate from there.</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>" I need to use "x3d.x3d". That's of course possible but a little cumbersome."<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:.5in'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Agreed on cumbersome!  Have you tried  <span class=apple-converted-space> </span></span><span style='font-size:9.0pt;font-family:"Courier New"'>import x3d.x3d as x3d_ <span class=apple-converted-space> </span></span><span style='font-size:14.0pt;font-family:"Monaco",serif'>?</span><span style='font-size:9.0pt;font-family:"Monaco",serif'><o:p></o:p></span></p></blockquote><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Sure (I even use import x3d.x3d as x3d). But it's not how most python packages work, stating with the standard library:<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>from os import chdir, not from os.os import chdir<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>from math import atanh, not from math.math import atanh<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>The same is true for common Python packages that are not part of the standard library:<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>import numpy as np; arr = np.ones(5), not import numpy.numpy as np<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>import pandas as pd, not import pandas.pandas as pd<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>It is of course your prerogative as package author to chose any naming scheme that seems sensible to you, but it is certainly unusual to import a package this way. It *does* make sense if you plan for more functionality in the future, e.g. if you think there could be other submodules such as<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.json<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.numpy_interface<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.utils<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.display<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>etc.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>If that's the case, maybe a short comment in the code that explains the reasoning would be useful.<o:p></o:p></span></p><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><p class=MsoNormal style='mso-margin-top-alt:auto;margin-bottom:12.0pt;margin-left:1.0in'><span style='font-size:9.0pt;font-family:"Monaco",serif'> <o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'> <o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>- the __init__.py file. The file is present, but not correct. It lists all the classes in __all__ but does not actually import them. Thus, that can't actually be used.<o:p></o:p></span></p><div style='margin-left:.5in'><p class=MsoNormal><span style='font-size:12.0pt'>Per<span class=apple-converted-space> </span><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.python.org%2F3%2Ftutorial%2Fmodules.html&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=nrwdjikfEifZx55a4PlZ87QneWVAO2nzfIqnzB%2B9J9c%3D&reserved=0" target="_blank"><span style='color:purple'>https://docs.python.org/3/tutorial/modules.html</span></a>, section 6.4: <span class=apple-converted-space> </span></span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:12.0pt'>"In the simplest case,<span class=m6872490181044312902apple-converted-space> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt'>__init__.py</span></span><span class=m6872490181044312902apple-converted-space><span style='font-size:12.0pt'> </span></span><span style='font-size:12.0pt'>can just be an empty file, but it can also execute initialization code for the package or set the<span class=m6872490181044312902apple-converted-space> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt'>__all__</span></span><span style='font-size:12.0pt'>variable, described later."</span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:12.0pt'> </span><o:p></o:p></p></div><div style='margin-left:.5in'><p class=MsoNormal><span style='font-size:12.0pt'>Per<span class=apple-converted-space> </span><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.python.org%2F3%2Ftutorial%2Fmodules.html&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=nrwdjikfEifZx55a4PlZ87QneWVAO2nzfIqnzB%2B9J9c%3D&reserved=0" target="_blank"><span style='color:purple'>https://docs.python.org/3/tutorial/modules.html</span></a>, section 6.4.1: <span class=apple-converted-space> </span></span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:12.0pt'>"Although certain modules are designed to export only names that follow certain patterns when you use </span><span style='font-size:11.5pt'>import *</span><span style='font-size:12.0pt'>, it is still considered bad practice in production code."</span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:12.0pt'> </span><o:p></o:p></p></div><div style='margin-left:.5in'><p class=MsoNormal><span style='font-size:12.0pt'>The "not actually import(ing) them part" is working as Python intends when we provide the empty __init__.py file (per 6.4.1)</span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:12.0pt'>If<span class=m6872490181044312902apple-converted-space> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt'>__all__</span></span><span class=m6872490181044312902apple-converted-space><span style='font-size:12.0pt'> </span></span><span style='font-size:12.0pt'>is not defined, the statement<span class=m6872490181044312902apple-converted-space> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt'>from</span></span><span class=m6872490181044312902apple-converted-space><span style='font-size:11.5pt'> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt'>sound.effects</span></span><span class=m6872490181044312902apple-converted-space><span style='font-size:11.5pt'> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt'>import</span></span><span class=m6872490181044312902apple-converted-space><span style='font-size:11.5pt'> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt'>*</span></span><span style='font-size:12.0pt'>does<span class=m6872490181044312902apple-converted-space> </span><em><span style='font-family:"Calibri",sans-serif'>not</span></em><span class=m6872490181044312902apple-converted-space> </span>import all submodules from the package<span class=m6872490181044312902apple-converted-space> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt;font-family:"Times New Roman",serif'>sound.effects</span></span><span class=m6872490181044312902apple-converted-space><span style='font-size:12.0pt'> </span></span><span style='font-size:12.0pt'>into the current namespace; it only ensures that the package<span class=m6872490181044312902apple-converted-space> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt;font-family:"Times New Roman",serif'>sound.effects</span></span><span class=m6872490181044312902apple-converted-space><span style='font-size:12.0pt'> </span></span><span style='font-size:12.0pt'>has been imported (possibly running any initialization code in<span class=m6872490181044312902apple-converted-space> </span></span><span class=m6872490181044312902pre><span style='font-size:11.5pt'>__init__.py</span></span><span style='font-size:12.0pt'>) and then imports whatever names are defined in the package.<span class=m6872490181044312902apple-converted-space> </span></span><o:p></o:p></p></div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:1.0in'><span style='font-size:14.0pt;font-family:"Monaco",serif'>The __all__ attribute gets initialized during the importing, but only as far as described. Thus requiring the package name prepend for fully-qualified names to properly resolve.</span><span style='font-size:9.0pt;font-family:"Monaco",serif'><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:.5in'><span style='font-size:14.0pt;font-family:"Monaco",serif'>We have chosen the empty __init__.py file convention for simplicity, as there is no forced loading of any leading underscore names into the _all__ attribute and/or namespace by using this convention (respecting 6.4.1).  This aspect is a future-proofing against having to consider if future code changes need to consider __all__ or not.  With the empty __init__.py there are no potential forcing issues with respect to future code updates.</span><span style='font-size:9.0pt;font-family:"Monaco",serif'><o:p></o:p></span></p></blockquote><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Well, you don't import anything, then there is no reason to define __all__ in the __init__ file. In that case the file should just be empty. As the paragraphs that you pasted above explain, the purpose of __all__ is to limit what gets imported when I do "from x3d import *" for example, if the following is my __init__.py:<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>from math import sqrt<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>from<span class=apple-converted-space> </span><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>__all__ = ['answer', 'MyClass']<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>answer = 5<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>class MyClass():<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>    def calc(self, x):<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>        return sqrt(x)<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'> <o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'> <o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>then "from xxx import *" gives me "answer" and "MyClass". Without the __all__ I would get "answer" "MyClass" and<span class=apple-converted-space> </span><br>"sqrt" i.e. everything that's available inside __init__.py. Often, that's not what we want because sqrt is nothing specific from our package. So __all__ restricts that. In the version of x3d.py that I have the __init__ files lists a whole bunch of things in the __all__, but does not import them. So why is there an __all__ at all?<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>However, the most common case is to selectively import things into __init__, often including things like a version string (as __version__) and the most important classes or functions that user may want in the flat namespace.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Examples from pretty standard Python packages:<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Furllib3%2Furllib3%2Fblob%2Fmain%2Fsrc%2Furllib3%2F__init__.py%23L27&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=GEG9iX3BhiLjgqnamGZ0JB7RkZPsd6DonSBmBxj7lbw%3D&reserved=0" target="_blank"><span style='color:purple'>https://github.com/urllib3/urllib3/blob/main/src/urllib3/__init__.py#L27</span></a><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fpypa%2Fsetuptools%2Fblob%2Fmain%2Fsetuptools%2F__init__.py%23L24&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=3Ia6E%2B%2BxZNhQzNdFLX%2FpjHIfznga%2F%2FwST087%2BZcjX68%3D&reserved=0" target="_blank"><span style='color:purple'>https://github.com/pypa/setuptools/blob/main/setuptools/__init__.py#L24</span></a><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnumpy%2Fnumpy%2Fblob%2Fmain%2Fnumpy%2F__init__.py&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=kwTQjz7mrDG1%2BtWMOXlbtMgTGXs4H9hKOVFSLC64FCs%3D&reserved=0" target="_blank"><span style='color:purple'>https://github.com/numpy/numpy/blob/main/numpy/__init__.py</span></a><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'> <o:p></o:p></span></p><p class=MsoNormal style='margin-bottom:12.0pt'> <o:p></o:p></p><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:.5in'><span style='font-size:14.0pt;font-family:"Monaco",serif'>Additionally, and as indicated by the bulk of the next two paragraphs, probably more importantly: I have been burned very badly in the past, entering Imports Hell, based on using an ill-timed from xyz import *   and had to explore the arcane and totally insane practice of putting import statements at the bottom of a file to partially attempt to compensate for import loading circular dependencies.  Putting<span class=apple-converted-space> </span></span><span style='font-size:9.0pt;font-family:"Courier New"'>from x3d import *</span><span style='font-size:9.0pt;font-family:"Monaco",serif'> <span class=apple-converted-space> </span></span><span style='font-size:14.0pt;font-family:"Monaco",serif'>into the __init__.py file opens the door to that netherworld which awaits someone unluckily coding something that creates a circular dependency.  I can't guarantee that there is zero chance of that in coding up a solution for Numpy types, or other kinds of types that may be necessary in the future.  We would hate to inadvertently force a package user into that special hell.</span><span style='font-size:9.0pt;font-family:"Monaco",serif'><o:p></o:p></span></p></blockquote><p class=MsoNormal style='margin-bottom:12.0pt'>I'm curious to learn how that works, since I've never seen a case where any other module imported anything from __init__.py Circular imports can happen and have happened to me, but never related to __init__, so I'm a little surprised. about that.<o:p></o:p></p><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:14.0pt;font-family:"Monaco",serif'> </span><span style='font-size:9.0pt;font-family:"Monaco",serif'><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>- Python usually makes heavy use of duck-typing (you can use any object as long as it behaves as you expect) instead of explicit "isinstance" checks. A lot of numerical computations in Python are done using the numpy (<a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fnumpy.org%2F&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=LgxVOCqqKyzUInTq%2FisxjCwQZR2Eyp89k8GuLqGxfoE%3D&reserved=0" target="_blank"><span style='color:purple'>https://numpy.org</span></a>) library, which implements array-based math and is optimized in C. Numpy has datatypes that are essentially similar to Python int but fail an isinstance checks, and I can pass those in some, but not all places in x3d.py. Here is an example that fails:<o:p></o:p></span></p><div style='margin-left:.5in'><p class=MsoNormal><span style='font-size:14.0pt'>We agree that this use-case needs addressing to provide a Numpy compliant x3d.py experience.  Please provide some feedback on following proposal, design goals/constraints first.</span><o:p></o:p></p></div><div style='margin-left:.5in'><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:14.0pt'>1) Yes, in the implementation code there is a point where duck-typing must become enforced typing, because the x3d module is for implementing a specified standard which has specified types.<span class=apple-converted-space> </span></span><o:p></o:p></p></div></blockquote><p class=MsoNormal style='margin-bottom:12.0pt'>But the specific standard is not the Python type. As I understand it the standard says "integer" not "64 bit integer in big-endian". If I'm correct, any int will do (32 bin on a 32 bit machine, 64 bit on a 64 bit machine etc.). If that's case, then there is in fact no reason at all to case e.g. a numpy int64 to a Python int - on a 64-bit machine they are identical anyway. When I output the x3d to an xml file or a json file, they will all be converted to a string anyway. Then, it's even less important what type of int they where initially, because you won't even see the difference between an int64 and an int128.<o:p></o:p></p><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:14.0pt'>So the type checking problem is unavoidable, it just comes down to at what layer of the code does a particular type run into an unavoidable requirement to finally do the type-check for a verified per-standard-construction.  The requirement has been addressed in code for the transition from basic types to the specified X3D types.  We know that so far this code works, so it would be nice to not rewrite all, or even any, of that working code.</span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:14.0pt'>2) Users who are using native Python types as inputs should not feel any performance change when adding the necessary Numpy type use functionality to module x3d. Adding mandatory casts, or even conditionals for deciding casts, could add significant overhead if millions+ of values are processed so targeting only where the price must be paid no-matter-what is advisable.</span><o:p></o:p></p></div></blockquote><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Performance is always and important consideration. However, it seems to me that this is premature optimization. We are not the first people thinking about this and it's not a bottleneck. On my machine, "if isinstance(a, int)" is about 1 ns faster than "int(a) = a" if a is an int already (that's the case of possible performance loss, if a is not an int already, then the current implementation fails anyway).<span class=apple-converted-space> </span><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>%timeit if isinstance(a, int): pass<o:p></o:p></span></p><pre>50.3 ns ± 0.266 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)<o:p></o:p></pre><pre>%timeit if int(a) == a: pass<o:p></o:p></pre><div><div><div><div><div><pre>51.4 ns ± 0.172 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)<o:p></o:p></pre></div></div></div></div></div><div><div><div><div><div><div><div><div><div><pre><span style='font-family:"Cambria Math",serif'>​</span><o:p></o:p></pre></div></div></div></div></div></div></div></div></div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>That 1 ns is only 2% of the total runtime of the if statement and < 0.04 % of the total runtime of executing something useful where that statement matters. Here, I making the smallest IndexedFaceSet I can.  If that takes 1 ns longer, that's OK. If I can afford to run a 26.3 microsecond operation a few million times, I can afford to run a 26.301 microsecond operation - the difference is within the noise of the measurement.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>%timeit out = x3d.IndexedFaceSet(coord=x3d.Coordinate(point=[(0, 0, 0), (0, 1, 0), (1, 1, 0)]), coordIndex=[0, 1, 2])<o:p></o:p></span></p><pre>26.3 µs ± 185 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)<o:p></o:p></pre><pre> <o:p></o:p></pre><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:14.0pt'>3) There must be some other communities out there, or in the future, that will have similar type issues specific to their use-case implementation, our Numpy solution should show the way forward for those, and in implementing those future updates require as little touching of verified-correct code as possible.</span><o:p></o:p></p></div></blockquote><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Numpy by far the most important one. While counting the importance of libraries is a tricky business, in e.g. PEP 465<span class=apple-converted-space> </span><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.python.org%2Fdev%2Fpeps%2Fpep-0465%2F%23but-isn-t-matrix-multiplication-a-pretty-niche-requirement&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=TYnWPaCmAD7qfI1yMWay2UaJjdGRPwXxxnyD8Vy7zCw%3D&reserved=0" target="_blank"><span style='color:purple'>https://www.python.org/dev/peps/pep-0465/#but-isn-t-matrix-multiplication-a-pretty-niche-requirement</span></a><span class=apple-converted-space> </span>the authors found that numpy was the forth most used library - ranking far before most packages of even the standard library (only sys, os, and re and imported more often). That does not mean that there is not and won't ever be other ways to do numerics in Python ever, but it does mean the numpy is a pretty save bet.<o:p></o:p></span></p><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><div style='margin-left:1.0in'><p class=MsoNormal><b><u><span style='font-size:14.0pt'>Proposal</span></u></b><span style='font-size:14.0pt'>:  Adding a submodule in the x3d module which serves as the interface layer between Numpy users and x3d.py.  Numpy users should only need to import their 'shim' from the x3d module  (As a non-binding name example: <span class=apple-converted-space> </span></span><span style='font-family:"Courier New"'>import x3d.numpy2x3d as x3d_</span><span style='font-size:14.0pt'>  I don't think I like the specific name either, but we all get the idea)   and it will provide Numpy-compliant type input, do any necessary type casting on parameters, and then call working x3d.py code. It should have an equivalent call for every public API function/method in x3d.py, but only include the minimal necessary type-casting code to make the call.  Once developed, well tested and verified, the long term maintenance tail of this shim file should be mostly restricted to times when Numpy makes changes to its type system (VERY rare), and if the x3d.py API gets any public additions (bugs are bugs, and that's not the tail I'm addressing here as we have the duty to kill as many as possible early.)</span><o:p></o:p></p></div></blockquote><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>I think that will work - but it's not the most convenient for the user. I think the most convenient would be to iterate over any input, and don't check that the input is a list<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>This works:<span class=apple-converted-space> </span><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.Coordinate(point=[[0, 0, 0], (0, 1, 0), (1, 1, 0)])<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>This fails:<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.Coordinate(point=([0, 0, 0], (0, 1, 0), (1, 1, 0)))<o:p></o:p></span></p><pre><span class=m6872490181044312902ansi-red-fg>X3DTypeError</span>: ([0, 0, 0], (0, 1, 0), (1, 1, 0)), type=<class 'tuple'> is not a valid Python list for MFVec3f<o:p></o:p></pre><div><p class=MsoNormal> <o:p></o:p></p></div><pre>Why not allow a tuple instead of a list here? The inner coordinates can be either tuples or lists.<o:p></o:p></pre><pre> <o:p></o:p></pre><pre>I don't understand what that typechecking is good for here.<o:p></o:p></pre><pre> <o:p></o:p></pre><pre>Moritz<o:p></o:p></pre><pre> <o:p></o:p></pre><p class=MsoNormal style='margin-bottom:12.0pt'> <o:p></o:p></p><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div style='margin-left:1.0in'><p class=MsoNormal><span style='font-size:14.0pt'>An added benefit of this flavor of solution is that your participation is not within the autogenerated x3d.py layer, so no concerns of breaking a working x3d.py file.  Writing this to be autogenerated as well is probably best practice, that way it significantly reduces eyeball-missed public API functions.  Don is the expert in the auto-generation aspect.  I helped him with x3d.py by describing the repeatable stylistic issues, conventions and some advantageous techniques to provide low-cost syntactic guarantees within chunks of code, he made the magic auto-happen, we debugged pairs style with him driving.  Setting up the Numpy-isms is likely a very similar flavor of project, but more favorably scoped as start-type and destination-type are both going to be defined the majority of the time, your expertise will be quite valuable in this process.</span><o:p></o:p></p></div></blockquote><p class=MsoNormal style='margin-bottom:12.0pt'>I have not started coding, but I would be surprised if more than 100 line of code are needed for this.<span class=apple-converted-space> </span><o:p></o:p></p><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:14.0pt'>Looking forward to seeing your thoughts.  Have a great weekend!</span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><div><div><div><div><p class=MsoNormal>v/r  Loren <o:p></o:p></p></div></div></div></div><div><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><div><p class=MsoNormal><span style='font-size:14.0pt'> </span><o:p></o:p></p></div><div style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in'><div><p class=MsoNormal><b><span style='font-size:12.0pt'>From:<span class=apple-converted-space> </span></span></b><span style='font-size:12.0pt'>Hans Moritz Guenther<span class=apple-converted-space> </span><a href="mailto:hgunther@mit.edu" target="_blank"><span style='color:purple'><hgunther@mit.edu></span></a><br><b>Date:<span class=apple-converted-space> </span></b>Monday, February 7, 2022 at 7:06 AM<br><b>To:<span class=apple-converted-space> </span></b>Don Brutzman<span class=apple-converted-space> </span><a href="mailto:brutzman@nps.edu" target="_blank"><span style='color:purple'><brutzman@nps.edu></span></a>, "Peitso, Loren (CIV)"<span class=apple-converted-space> </span><a href="mailto:lepeitso@nps.edu" target="_blank"><span style='color:purple'><lepeitso@nps.edu></span></a><br><b>Subject:<span class=apple-converted-space> </span></b>x3d.py package: Some feedback and suggestion for improvement</span><o:p></o:p></p></div></div><div><div><p class=MsoNormal> <o:p></o:p></p></div></div><div style='border:solid #004679 1.0pt;padding:2.0pt 2.0pt 2.0pt 2.0pt'><div><p class=MsoNormal style='line-height:12.0pt;background:#004679'><span style='font-size:10.0pt;color:yellow'>NPS WARNING: *external sender* verify before acting.</span><o:p></o:p></p></div></div><div><p class=MsoNormal> <o:p></o:p></p></div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Hi,<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>I'm starting to use the x3d.py library to generate x3d output.<span class=apple-converted-space> </span><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>For a little bit of background, I'm an astronomer and one of the things I do is ray-tracing of the designs for new instruments. It is then very useful to have some form of output that allows me to put images of how the instrument looks and what path the photons take into presentations or on the web. As it turns out, X3D is a great format for that, see e.g.<span class=apple-converted-space> </span><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fspace.mit.edu%2Fhome%2Fguenther%2FARCUS%2F3Dview.html&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=R9pQbefHVGoQ25HNMrE6j8ha7nfKEOztUmZRe7jpt7M%3D&reserved=0" target="_blank"><span style='color:purple'>https://space.mit.edu/home/guenther/ARCUS/3Dview.html</span></a><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>In that past, I've generated the X3D output through a python package called mayavi (<a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.enthought.com%2Fmayavi%2Fmayavi%2F&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=eigxM5pQOtf2DEKROwYLBS7x3p0zrLINjUazRDvVax0%3D&reserved=0" target="_blank"><span style='color:purple'>https://docs.enthought.com/mayavi/mayavi/</span></a>) but that is a rather heavy dependency for this very limited purpose. So, I'm trying to convert to use your x3d.py library instead.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>I'm very much a Python programmer using what people call the "scientific stack" in Python (the libraries numpy, scipy, pandas, etc.) with very little experience in 3D visualization or web-programming. First, let me thank you for your effort to make x3d.py at all. In general it works great!<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>I'd like to mention a few glitches I've run into so far, and since I did not see in your package description what's the preferred way to give feedback I decided to just email you. Please let me know if you prefer me to raise those in a different forum (mailing list, sourceforge ticket ...).<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>I might be able to help with some of this, but since you say your package is autogenerated, there is little use for me to change the code I have; presumably all changes need to be done to the code that you use to autogenerate things.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>OK, here are a few things I noticed:<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>- the __init__.py file. The file is present, but not correct. It lists all the classes in __all__ but does not actually import them. Thus, that can't actually be used.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>I</span><span style='font-size:9.0pt;font-family:"Courier New"'>n [1]: import x3d<br><br>In [2]: x3d.IndexedTriangleSet<br>---------------------------------------------------------------------------<br>AttributeError                            Traceback (most recent call last)<br><ipython-input-2-93a98d5f0414> in <module><br>----> 1 x3d.IndexedTriangleSet</span><span style='font-size:9.0pt;font-family:"Monaco",serif'><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Instead, I need to use "x3d.x3d". That's of course possible but a little cumbersome.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Courier New"'>In [4]: import x3d.x3d<br>x3d.py package loaded, have fun with X3D Graphics!<br><br>In [5]: x3d.x3d.IndexedTriangleSet<br>Out[5]: x3d.x3d.IndexedTriangleSet</span><span style='font-size:9.0pt;font-family:"Monaco",serif'><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>I think all that's missing is the following line in the __init__.py<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Courier New"'>from x3d import *</span><span style='font-size:9.0pt;font-family:"Monaco",serif'><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>which will import everything that's defined in x3d.py into the __init__.py namespace and than the user an get it from "import x3d" which gives you the names defined in x3d/__init__.py<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>- IndexTriangleSet: Coordinates are given as a list of tuples [(x1, y1, z1), (x2, y2, y3), ...]. I think that makes sense. It orders stuff in a natural way and is easy to understand. However, the index needs to be given as a flat list [ind11, ind12, ind13, ind21, ind22, ind23, ...]. Since there are three indices per triangle, I think the same list of tuples as for the coordinates would make more sense [( ind11, ind12, ind13), (ind21, ind22, ind23) ...]<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>- Python usually makes heavy use of duck-typing (you can use any object as long as it behaves as you expect) instead of explicit "isinstance" checks. A lot of numerical computations in Python are done using the numpy (<a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fnumpy.org%2F&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610730103%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=LgxVOCqqKyzUInTq%2FisxjCwQZR2Eyp89k8GuLqGxfoE%3D&reserved=0" target="_blank"><span style='color:purple'>https://numpy.org</span></a>) library, which implements array-based math and is optimized in C. Numpy has datatypes that are essentially similar to Python int but fail an isinstance checks, and I can pass those in some, but not all places in x3d.py. Here is an example that fails:<o:p></o:p></span></p><pre> <o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-fg>~/mambaforge/envs/kitchensink/lib/python3.10/site-packages/x3d/x3d.py</span> in <span class=m6872490181044312902ansi-cyan-fg>__init__</span><span class=m6872490181044312902ansi-blue-fg>(self, ccw, colorPerVertex, index, normalPerVertex, solid, color, coord, fogCoord, normal, texCoord, attrib, DEF, USE, IS, metadata, class_, id_, style_)</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>  48191</span>         self<span class=m6872490181044312902ansi-blue-fg>.</span>ccw <span class=m6872490181044312902ansi-blue-fg>=</span> ccw<o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>  48192</span>         self<span class=m6872490181044312902ansi-blue-fg>.</span>colorPerVertex <span class=m6872490181044312902ansi-blue-fg>=</span> colorPerVertex<o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-fg>> 48193</span><span class=m6872490181044312902ansi-red-fg>         </span>self<span class=m6872490181044312902ansi-blue-fg>.</span>index <span class=m6872490181044312902ansi-blue-fg>=</span> index<o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>  48194</span>         self<span class=m6872490181044312902ansi-blue-fg>.</span>normalPerVertex <span class=m6872490181044312902ansi-blue-fg>=</span> normalPerVertex<o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>  48195</span>         self<span class=m6872490181044312902ansi-blue-fg>.</span>solid <span class=m6872490181044312902ansi-blue-fg>=</span> solid<o:p></o:p></pre><pre> <o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-fg>~/mambaforge/envs/kitchensink/lib/python3.10/site-packages/x3d/x3d.py</span> in <span class=m6872490181044312902ansi-cyan-fg>index</span><span class=m6872490181044312902ansi-blue-fg>(self, index)</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>  48230</span>         <span class=m6872490181044312902ansi-green-fg>if</span>  index <span class=m6872490181044312902ansi-green-fg>is</span> <span class=m6872490181044312902ansi-green-fg>None</span><span class=m6872490181044312902ansi-blue-fg>:</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>  48231</span>             index <span class=m6872490181044312902ansi-blue-fg>=</span> MFInt32<span class=m6872490181044312902ansi-blue-fg>.</span>DEFAULT_VALUE<span class=m6872490181044312902ansi-blue-fg>()</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-fg>> 48232</span><span class=m6872490181044312902ansi-red-fg>         </span>assertValidMFInt32<span class=m6872490181044312902ansi-blue-fg>(</span>index<span class=m6872490181044312902ansi-blue-fg>)</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>  48233</span>         assertNonNegative<span class=m6872490181044312902ansi-blue-fg>('index',</span> index<span class=m6872490181044312902ansi-blue-fg>)</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>  48234</span>         self<span class=m6872490181044312902ansi-blue-fg>.</span>__index <span class=m6872490181044312902ansi-blue-fg>=</span> index<o:p></o:p></pre><pre> <o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-fg>~/mambaforge/envs/kitchensink/lib/python3.10/site-packages/x3d/x3d.py</span> in <span class=m6872490181044312902ansi-cyan-fg>assertValidMFInt32</span><span class=m6872490181044312902ansi-blue-fg>(value)</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>   2622</span>         <span class=m6872490181044312902ansi-green-fg>if</span> <span class=m6872490181044312902ansi-green-fg>not</span> isinstance<span class=m6872490181044312902ansi-blue-fg>(</span>each<span class=m6872490181044312902ansi-blue-fg>,</span> int<span class=m6872490181044312902ansi-blue-fg>):</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>   2623</span>             <span class=m6872490181044312902ansi-red-fg># print(flush=True)</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-fg>-> 2624</span><span class=m6872490181044312902ansi-red-fg>             </span><span class=m6872490181044312902ansi-green-fg>raise</span> X3DTypeError<span class=m6872490181044312902ansi-blue-fg>('MFInt32 list has contained value='</span> <span class=m6872490181044312902ansi-blue-fg>+</span> str<span class=m6872490181044312902ansi-blue-fg>(</span>each<span class=m6872490181044312902ansi-blue-fg>)</span> <span class=m6872490181044312902ansi-blue-fg>+</span> <span class=m6872490181044312902ansi-blue-fg>' with type='</span> <span class=m6872490181044312902ansi-blue-fg>+</span> str<span class=m6872490181044312902ansi-blue-fg>(</span>type<span class=m6872490181044312902ansi-blue-fg>(</span>each<span class=m6872490181044312902ansi-blue-fg>))</span> <span class=m6872490181044312902ansi-blue-fg>+</span> <span class=m6872490181044312902ansi-blue-fg>' which is not a valid int')</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>   2625</span>     <span class=m6872490181044312902ansi-green-fg>if</span> <span class=m6872490181044312902ansi-green-fg>not</span> isValidMFInt32<span class=m6872490181044312902ansi-blue-fg>(</span>value<span class=m6872490181044312902ansi-blue-fg>):</span><o:p></o:p></pre><pre><span class=m6872490181044312902ansi-green-intense-fg>   2626</span>         <span class=m6872490181044312902ansi-red-fg># print(flush=True)</span><o:p></o:p></pre><pre> <o:p></o:p></pre><pre><span class=m6872490181044312902ansi-red-fg>X3DTypeError</span>: MFInt32 list has contained value=1 with type=<class 'numpy.int64'> which is not a valid int<o:p></o:p></pre><pre> <o:p></o:p></pre><pre> <o:p></o:p></pre><pre>There is an easy workaround:<o:p></o:p></pre><pre> <o:p></o:p></pre><pre>x3d.IndexedTriangleSet(index = [int(x) for x in myindex]<o:p></o:p></pre><pre> <o:p></o:p></pre><pre>but it would be nice if IndexedTriangleSet accepted my numbers directly. <o:p></o:p></pre><pre>There are several ways of doing that, but the easiest is probably to change line 2622 to:<o:p></o:p></pre><pre> <o:p></o:p></pre><pre>if not int(x) == x: <o:p></o:p></pre><pre> <o:p></o:p></pre><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>That will work for any object that can be converted to an int, including numpy, python decimal, fraction, ..<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>- Numpy: One might consider taking numpy arrays directly, i.e. instead of<span class=apple-converted-space> </span><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.Coordinate(point=[(x1, y1, z1), (x2, y2, y3), ...])<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>one could do<span class=apple-converted-space> </span><o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>x3d.Coordinate(point=arr)<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>where arr is a (3, n) numpy array. Now, if done naively that would require numpy as a dependency to x3d.py and it's probably good to avoid that. However, there are ways to accept numpy arrays without requiring numpy. That's a little more involved, but can be done (for example using decorators or a separate module (x3d.numpy_interface) or separate package (x3d-numpy)). Not sure if it's worth the effort at this point - that depends on what your future plans for this package are and how fast this is developing.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>- Changelog. From the pypi entry and the docs on<span class=apple-converted-space> </span><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.web3d.org%2Fx3d%2Fstylesheets%2Fpython%2Fpython.html&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610886323%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=MizyC1goMdfbZ5TYbIADty6HUJ%2BVurSPuyMUfdWmnOs%3D&reserved=0" target="_blank"><span style='color:purple'>https://www.web3d.org/x3d/stylesheets/python/python.html</span></a><span class=apple-converted-space> </span>it was not quite clear to me how stable the package is or where I would see changes listed, for example, if you do the change that I suggested above (accepting index values as tuples instead of a flat list) that would break the interface. Would you do that? Where would I find a list of changes from one version to another?<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>- Jupyter notebook: I'm working on a wrapper to automatically display any x3d representation in the jupyter notebook. It's only a few lines of code, and I'm happy to share (it could be integrated into the Python package x3d easily), but I want to use it a little longer for myself to make sure I have the kinks worked out so I don't pass code with major bugs to you.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Please let me know if there is anything I can do to help with this awesome package, that really makes generating X3D from Python so much simpler already.<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Yours,<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'>Moritz<o:p></o:p></span></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:9.0pt;font-family:"Monaco",serif'> <o:p></o:p></span></p><pre>-- <o:p></o:p></pre><pre>Hans Moritz Günther<o:p></o:p></pre><pre>Massachusetts Institute of Technology<o:p></o:p></pre><pre>Kavli Institute for Astrophysics and Space Research<o:p></o:p></pre><pre><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.google.com%2Fmaps%2Fsearch%2F77%2BMassachusetts%2BAvenue%3Fentry%3Dgmail%26source%3Dg&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610886323%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=p15QJHvTTe7AV4iLY8powKU0ygsiUenqD%2B7ySu3WFhk%3D&reserved=0"><span style='color:purple'>77 Massachusetts Avenue</span></a><o:p></o:p></pre><pre>NE83-569<o:p></o:p></pre><pre>Cambridge, MA 02139<o:p></o:p></pre><pre><a href="mailto:hgunther@mit.edu" target="_blank"><span style='color:purple'>hgunther@mit.edu</span></a><o:p></o:p></pre><pre><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fspace.mit.edu%2Fhome%2Fguenther%2F&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610886323%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=%2FDLUzYkzMAB0GCYLX3Gdzum3IXSwB8r7qp%2FaolK8plM%3D&reserved=0" target="_blank"><span style='color:purple'>https://space.mit.edu/home/guenther/</span></a><o:p></o:p></pre></div></blockquote><pre>-- <o:p></o:p></pre><pre>Hans Moritz Günther<o:p></o:p></pre><pre>Massachusetts Institute of Technology<o:p></o:p></pre><pre>Kavli Institute for Astrophysics and Space Research<o:p></o:p></pre><pre><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.google.com%2Fmaps%2Fsearch%2F77%2BMassachusetts%2BAvenue%3Fentry%3Dgmail%26source%3Dg&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610886323%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=p15QJHvTTe7AV4iLY8powKU0ygsiUenqD%2B7ySu3WFhk%3D&reserved=0"><span style='color:purple'>77 Massachusetts Avenue</span></a><o:p></o:p></pre><pre>NE83-569<o:p></o:p></pre><pre>Cambridge, MA 02139<o:p></o:p></pre><pre><a href="mailto:hgunther@mit.edu" target="_blank"><span style='color:purple'>hgunther@mit.edu</span></a><o:p></o:p></pre><pre><a href="https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fspace.mit.edu%2Fhome%2Fguenther%2F&data=04%7C01%7Cbrutzman%40nps.edu%7Ca9d858d0c9e94448f9eb08d9fbab6dd1%7C6d936231a51740ea9199f7578963378e%7C0%7C0%7C637817536610886323%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0&sdata=%2FDLUzYkzMAB0GCYLX3Gdzum3IXSwB8r7qp%2FaolK8plM%3D&reserved=0" target="_blank"><span style='color:purple'>https://space.mit.edu/home/guenther/</span></a><o:p></o:p></pre></div></div></div><div><p class=MsoNormal>_______________________________________________<br>x3d-public mailing list<br><a href="mailto:x3d-public@web3d.org" target="_blank"><span style='color:purple'>x3d-public@web3d.org</span></a><br><a href="http://web3d.org/mailman/listinfo/x3d-public_web3d.org" target="_blank"><span style='color:purple'>http://web3d.org/mailman/listinfo/x3d-public_web3d.org</span></a><o:p></o:p></p></div></blockquote></div></div></div><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Monaco",serif'>_______________________________________________<br>x3d-public mailing list<br></span><a href="mailto:x3d-public@web3d.org"><span style='font-size:9.0pt;font-family:"Monaco",serif;color:purple'>x3d-public@web3d.org</span></a><span style='font-size:9.0pt;font-family:"Monaco",serif'><br></span><a href="http://web3d.org/mailman/listinfo/x3d-public_web3d.org"><span style='font-size:9.0pt;font-family:"Monaco",serif;color:purple'>http://web3d.org/mailman/listinfo/x3d-public_web3d.org</span></a><o:p></o:p></p></div></blockquote></div><p class=MsoNormal><o:p> </o:p></p></div></div></div></body></html>