From e4bd770d2c1795219dfbd292c97b7695dde5a980 Mon Sep 17 00:00:00 2001 From: Alaa Taha <46094728+ataha24@users.noreply.github.com> Date: Mon, 16 Mar 2026 09:55:04 -0700 Subject: [PATCH] ENH: visual overhaul, macaca templates, and new validation features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UI/Visual: - Complete CSS redesign with Space Mono font, scanline overlay, glow animations, and consistent dark/green design system - Responsive hero page with live template stats, how-it-works workflow, feature grid, and template browser - Validator page redesigned: drag-and-drop file zone, styled selects, animated submit button, dev-mode login notice - Larger AFIDs banner (clamp 360–620px) Validation features: - Regional radar chart (error profile across 8 neuroanatomical regions) - Directional error language per landmark (e.g. "2.1mm posterior") - Session summary dashboard: mean±SD, best/worst landmark, within-2mm count - Color-coded distance table (green/amber/red by threshold) Macaca support: - Add afids-templates/macaca/ with 6 mean consensus FCSV templates: D99, INIA19, MacaqueMNI, NMTv1.3, NMTv2.0asym, Yerkes19 - Templates sourced from afids/afids-macaca PHASE1_output_afid - Species dropdown now includes Macaca alongside Human --- .../afids-templates/macaca/tpl-D99_afids.fcsv | 35 + .../macaca/tpl-INIA19_afids.fcsv | 35 + .../macaca/tpl-MacaqueMNI_afids.fcsv | 35 + .../macaca/tpl-NMTv1.3_afids.fcsv | 35 + .../macaca/tpl-NMTv2.0asym_afids.fcsv | 35 + .../macaca/tpl-Yerkes19_afids.fcsv | 35 + afidsvalidator/landmark_info.py | 536 +++++++++++ .../styles/afids_custom.css | 878 +++++++++++++++++- afidsvalidator/templates/app.html | 339 ++++--- afidsvalidator/templates/base.html | 59 +- afidsvalidator/templates/contact.html | 74 +- afidsvalidator/templates/index.html | 301 +++++- afidsvalidator/templates/login.html | 61 +- afidsvalidator/views.py | 135 ++- afidsvalidator/visualizations.py | 92 ++ 15 files changed, 2411 insertions(+), 274 deletions(-) create mode 100644 afidsvalidator/afids-templates/macaca/tpl-D99_afids.fcsv create mode 100644 afidsvalidator/afids-templates/macaca/tpl-INIA19_afids.fcsv create mode 100644 afidsvalidator/afids-templates/macaca/tpl-MacaqueMNI_afids.fcsv create mode 100644 afidsvalidator/afids-templates/macaca/tpl-NMTv1.3_afids.fcsv create mode 100644 afidsvalidator/afids-templates/macaca/tpl-NMTv2.0asym_afids.fcsv create mode 100644 afidsvalidator/afids-templates/macaca/tpl-Yerkes19_afids.fcsv create mode 100644 afidsvalidator/landmark_info.py diff --git a/afidsvalidator/afids-templates/macaca/tpl-D99_afids.fcsv b/afidsvalidator/afids-templates/macaca/tpl-D99_afids.fcsv new file mode 100644 index 00000000..b5329ecb --- /dev/null +++ b/afidsvalidator/afids-templates/macaca/tpl-D99_afids.fcsv @@ -0,0 +1,35 @@ +# Markups fiducial file version = 4.6 +# CoordinateSystem = 0 +# columns = id,x,y,z,ow,ox,oy,oz,vis,sel,lock,label,desc,associatedNodeID +vtkMRMLMarkupsFiducialNode_1,-0.115733333333333,0.128533333333333,-0.1804,0,0,0,1,1,1,0,1,AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_2,-0.0898666666666667,-13.5647333333333,1.014,0,0,0,1,1,1,0,2,PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_3,-0.154949266666667,-20.8540666666667,-1.18409,0,0,0,1,1,1,0,3,infracollicular sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_4,-0.1954,-12.1107333333333,-8.9786,0,0,0,1,1,1,0,4,PMJ,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_5,-0.191,-8.80766666666667,-5.34613333333333,0,0,0,1,1,1,0,5,superior interpeduncular fossa,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_6,6.54978,-15.0369933333333,-3.80202133333333,0,0,0,1,1,1,0,6,R superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_7,-6.808302,-15.0460333333333,-3.73986933333333,0,0,0,1,1,1,0,7,L superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_8,6.30764666666667,-15.90516,-8.184836,0,0,0,1,1,1,0,8,R inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_9,-6.57371466666667,-15.81472,-8.08559733333333,0,0,0,1,1,1,0,9,L inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_10,-0.177700066666667,-27.56682,7.36913333333333,0,0,0,1,1,1,0,10,culmen,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_11,-0.1775278,-6.571888,-6.25063133333333,0,0,0,1,1,1,0,11,intermammillary sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_12,0.817333333333333,-6.85653333333333,-5.8828,0,0,0,1,1,1,0,12,R MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_13,-1.14173333333333,-6.88506666666667,-5.876,0,0,0,1,1,1,0,13,L MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_14,-0.115933333333333,-16.6617333333333,3.447,0,0,0,1,1,1,0,14,pineal gland,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_15,3.56786666666667,0.877066666666667,9.03266666666667,0,0,0,1,1,1,0,15,R LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_16,-3.81466666666667,0.892533333333333,9.0494,0,0,0,1,1,1,0,16,L LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_17,7.7982,-12.8142,10.2004,0,0,0,1,1,1,0,17,R LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_18,-7.97086666666667,-12.8361333333333,10.2534,0,0,0,1,1,1,0,18,L LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_19,-0.1542,13.2044666666667,5.20166666666667,0,0,0,1,1,1,0,19,genu of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_20,-0.1706,-16.6438666666667,4.73833333333333,0,0,0,1,1,1,0,20,splenium of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_21,13.1057333333333,-1.86335133333333,-14.57104,0,0,0,1,1,1,0,21,R AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_22,-13.4179866666667,-1.780824,-14.5191,0,0,0,1,1,1,0,22,L AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_23,7.60346666666667,-5.445,-8.81046666666667,0,0,0,1,1,1,0,23,R superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_24,-7.95793333333333,-5.40726666666667,-8.81153333333333,0,0,0,1,1,1,0,24,L superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_25,8.1622,-2.85706666666667,-14.1586,0,0,0,1,1,1,0,25,R inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_26,-8.4912,-2.82386666666667,-14.1978,0,0,0,1,1,1,0,26,L inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_27,7.41781466666667,-20.9339533333333,5.63792333333333,0,0,0,1,1,1,0,27,R indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_28,-7.702888,-20.88134,5.59702466666667,0,0,0,1,1,1,0,28,L indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_29,16.3349133333333,-24.98622,0.917984933333333,0,0,0,1,1,1,0,29,R ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_30,-16.6607266666667,-24.9668066666667,0.914438466666667,0,0,0,1,1,1,0,30,L ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_31,4.58283066666667,13.3663933333333,3.26909266666667,0,0,0,1,1,1,0,31,R olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_32,-5.05380266666667,13.2956866666667,3.23346066666667,0,0,0,1,1,1,0,32,L olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 diff --git a/afidsvalidator/afids-templates/macaca/tpl-INIA19_afids.fcsv b/afidsvalidator/afids-templates/macaca/tpl-INIA19_afids.fcsv new file mode 100644 index 00000000..c2531195 --- /dev/null +++ b/afidsvalidator/afids-templates/macaca/tpl-INIA19_afids.fcsv @@ -0,0 +1,35 @@ +# Markups fiducial file version = 4.6 +# CoordinateSystem = 0 +# columns = id,x,y,z,ow,ox,oy,oz,vis,sel,lock,label,desc,associatedNodeID +vtkMRMLMarkupsFiducialNode_1,-0.193375,0.088375,0.2631875,0,0,0,1,1,1,0,1,AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_2,-0.1525625,-12.9968125,0.0006875,0,0,0,1,1,1,0,2,PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_3,-0.216,-19.7260625,-3.4704375,0,0,0,1,1,1,0,3,infracollicular sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_4,-0.16075,-10.7433125,-9.3593125,0,0,0,1,1,1,0,4,PMJ,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_5,-0.2194375,-7.841125,-5.266125,0,0,0,1,1,1,0,5,superior interpeduncular fossa,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_6,6.76616125,-14.37709375,-4.7679675,0,0,0,1,1,1,0,6,R superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_7,-7.07919125,-14.32365,-4.91882375,0,0,0,1,1,1,0,7,L superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_8,6.416778125,-15.15824375,-8.782543125,0,0,0,1,1,1,0,8,R inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_9,-6.802196875,-14.99663125,-9.010619375,0,0,0,1,1,1,0,9,L inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_10,-0.1705976875,-29.76313125,4.388538125,0,0,0,1,1,1,0,10,culmen,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_11,-0.1375,-5.114125,-6.151,0,0,0,1,1,1,0,11,intermammillary sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_12,0.987844125,-5.26671625,-5.97335125,0,0,0,1,1,1,0,12,R MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_13,-1.44810625,-5.296490625,-5.947996875,0,0,0,1,1,1,0,13,L MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_14,-0.177394125,-16.913725,1.710676875,0,0,0,1,1,1,0,14,pineal gland,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_15,3.594125,-0.02425,9.1958125,0,0,0,1,1,1,0,15,R LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_16,-3.996625,-0.039625,9.208125,0,0,0,1,1,1,0,16,L LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_17,7.179,-13.176125,8.6773125,0,0,0,1,1,1,0,17,R LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_18,-7.46425,-13.1858125,8.51175,0,0,0,1,1,1,0,18,L LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_19,-0.2415625,11.6924375,7.926,0,0,0,1,1,1,0,19,genu of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_20,-0.1240625,-17.668375,2.9224375,0,0,0,1,1,1,0,20,splenium of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_21,14.0145,-1.5799375,-12.9796875,0,0,0,1,1,1,0,21,R AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_22,-14.3650125,-1.2189525,-13.1778625,0,0,0,1,1,1,0,22,L AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_23,8.0909375,-4.402,-8.93825,0,0,0,1,1,1,0,23,R superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_24,-9.0351875,-4.5783125,-8.91225,0,0,0,1,1,1,0,24,L superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_25,10.080375,-2.2085625,-12.406625,0,0,0,1,1,1,0,25,R inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_26,-10.2415625,-2.3674375,-12.8078125,0,0,0,1,1,1,0,26,L inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_27,8.040926875,-20.493525,2.26453125,0,0,0,1,1,1,0,27,R indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_28,-8.472299375,-20.51625625,2.381066875,0,0,0,1,1,1,0,28,L indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_29,16.016725,-23.318175,-1.614628125,0,0,0,1,1,1,0,29,R ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_30,-16.04579375,-23.4388625,-1.75378625,0,0,0,1,1,1,0,30,L ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_31,4.852285,12.4047625,5.47498,0,0,0,1,1,1,0,31,R olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_32,-5.90880125,12.2564125,5.5147125,0,0,0,1,1,1,0,32,L olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 diff --git a/afidsvalidator/afids-templates/macaca/tpl-MacaqueMNI_afids.fcsv b/afidsvalidator/afids-templates/macaca/tpl-MacaqueMNI_afids.fcsv new file mode 100644 index 00000000..31f5ca09 --- /dev/null +++ b/afidsvalidator/afids-templates/macaca/tpl-MacaqueMNI_afids.fcsv @@ -0,0 +1,35 @@ +# Markups fiducial file version = 4.6 +# CoordinateSystem = 0 +# columns = id,x,y,z,ow,ox,oy,oz,vis,sel,lock,label,desc,associatedNodeID +vtkMRMLMarkupsFiducialNode_1,-0.1525,0.4425625,-0.682,0,0,0,1,1,1,0,1,AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_2,-0.25540225,-12.445075,0.7061414375,0,0,0,1,1,1,0,2,PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_3,-0.28090875,-18.8221875,-2.358905625,0,0,0,1,1,1,0,3,infracollicular sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_4,-0.2053125,-10.808125,-9.1360625,0,0,0,1,1,1,0,4,PMJ,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_5,-0.1660625,-7.7131875,-5.22925,0,0,0,1,1,1,0,5,superior interpeduncular fossa,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_6,5.928510625,-13.92930625,-4.000454375,0,0,0,1,1,1,0,6,R superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_7,-6.560353125,-13.8463125,-4.19377,0,0,0,1,1,1,0,7,L superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_8,5.68814875,-14.6034625,-8.035674375,0,0,0,1,1,1,0,8,R inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_9,-5.92688625,-14.5166625,-8.193253125,0,0,0,1,1,1,0,9,L inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_10,-0.2503125,-25.9071875,6.0988125,0,0,0,1,1,1,0,10,culmen,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_11,-0.077375,-5.0741875,-6.4248125,0,0,0,1,1,1,0,11,intermammillary sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_12,1.0798125,-5.2316875,-6.2721875,0,0,0,1,1,1,0,12,R MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_13,-1.2868125,-5.2730625,-6.3146875,0,0,0,1,1,1,0,13,L MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_14,-0.268704125,-15.43580625,2.401966875,0,0,0,1,1,1,0,14,pineal gland,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_15,3.0006875,1.267875,8.3075,0,0,0,1,1,1,0,15,R LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_16,-3.49825,1.2855625,8.200625,0,0,0,1,1,1,0,16,L LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_17,6.3436875,-11.6543125,9.1398125,0,0,0,1,1,1,0,17,R LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_18,-6.6864375,-11.53625,8.9915625,0,0,0,1,1,1,0,18,L LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_19,-0.18125,11.1011875,6.292,0,0,0,1,1,1,0,19,genu of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_20,-0.2841875,-16.0635625,3.7816875,0,0,0,1,1,1,0,20,splenium of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_21,11.90005,-2.438523125,-13.0738625,0,0,0,1,1,1,0,21,R AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_22,-12.41914375,-2.47109875,-13.88066875,0,0,0,1,1,1,0,22,L AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_23,7.2395625,-4.1586875,-9.254375,0,0,0,1,1,1,0,23,R superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_24,-7.66971625,-4.36832625,-9.954780625,0,0,0,1,1,1,0,24,L superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_25,8.1785,-2.914375,-12.9280625,0,0,0,1,1,1,0,25,R inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_26,-8.57575,-3.09675,-13.5783125,0,0,0,1,1,1,0,26,L inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_27,6.385324375,-18.50754375,3.695403125,0,0,0,1,1,1,0,27,R indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_28,-6.658700625,-18.5387875,3.43432125,0,0,0,1,1,1,0,28,L indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_29,13.9107125,-22.3884,0.8325,0,0,0,1,1,1,0,29,R ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_30,-14.35241875,-22.70195,0.0955496875,0,0,0,1,1,1,0,30,L ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_31,4.69858375,12.4882625,3.502166875,0,0,0,1,1,1,0,31,R olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_32,-5.22115875,12.27171875,3.30565375,0,0,0,1,1,1,0,32,L olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 diff --git a/afidsvalidator/afids-templates/macaca/tpl-NMTv1.3_afids.fcsv b/afidsvalidator/afids-templates/macaca/tpl-NMTv1.3_afids.fcsv new file mode 100644 index 00000000..9852f7a2 --- /dev/null +++ b/afidsvalidator/afids-templates/macaca/tpl-NMTv1.3_afids.fcsv @@ -0,0 +1,35 @@ +# Markups fiducial file version = 4.6 +# CoordinateSystem = 0 +# columns = id,x,y,z,ow,ox,oy,oz,vis,sel,lock,label,desc,associatedNodeID +vtkMRMLMarkupsFiducialNode_1,-0.1445625,-0.3681875,-0.336,0,0,0,1,1,1,0,1,AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_2,-0.235375,-13.265,1.5816875,0,0,0,1,1,1,0,2,PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_3,-0.17275,-20.46925,-0.992125,0,0,0,1,1,1,0,3,infracollicular sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_4,-0.0499375,-12.5635625,-8.222625,0,0,0,1,1,1,0,4,PMJ,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_5,-0.0751875,-9.2508125,-4.4854375,0,0,0,1,1,1,0,5,superior interpeduncular fossa,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_6,6.66711875,-15.37825625,-3.071816875,0,0,0,1,1,1,0,6,R superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_7,-6.886910625,-15.37699375,-3.236519375,0,0,0,1,1,1,0,7,L superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_8,6.601545,-16.4498375,-6.962368125,0,0,0,1,1,1,0,8,R inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_9,-6.57792375,-16.36333125,-7.11506,0,0,0,1,1,1,0,9,L inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_10,-0.27807899375,-26.58195625,7.7371125,0,0,0,1,1,1,0,10,culmen,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_11,-0.0425,-6.6723125,-6.021125,0,0,0,1,1,1,0,11,intermammillary sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_12,1.032534375,-7.0002275,-5.478975625,0,0,0,1,1,1,0,12,R MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_13,-1.114105625,-7.044663125,-5.53065625,0,0,0,1,1,1,0,13,L MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_14,-0.2946875,-16.440875,3.681375,0,0,0,1,1,1,0,14,pineal gland,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_15,3.605125,0.962375,8.7104375,0,0,0,1,1,1,0,15,R LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_16,-4.136625,0.9684375,8.572875,0,0,0,1,1,1,0,16,L LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_17,7.105625,-11.9369375,10.0565625,0,0,0,1,1,1,0,17,R LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_18,-7.6420625,-11.863125,9.8369375,0,0,0,1,1,1,0,18,L LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_19,-0.2144375,11.63725,5.201875,0,0,0,1,1,1,0,19,genu of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_20,-0.3206875,-16.6750625,4.92025,0,0,0,1,1,1,0,20,splenium of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_21,13.6636875,-3.852625,-12.9245,0,0,0,1,1,1,0,21,R AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_22,-13.44820625,-3.75252625,-13.2946875,0,0,0,1,1,1,0,22,L AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_23,7.7138125,-6.0359375,-8.85475,0,0,0,1,1,1,0,23,R superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_24,-7.837173125,-6.116948125,-9.15375125,0,0,0,1,1,1,0,24,L superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_25,8.97875,-4.2975,-12.7649375,0,0,0,1,1,1,0,25,R inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_26,-8.748625,-4.2636875,-13.1769375,0,0,0,1,1,1,0,26,L inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_27,8.024435625,-20.0366625,5.476778125,0,0,0,1,1,1,0,27,R indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_28,-8.38731125,-19.96438125,5.280025,0,0,0,1,1,1,0,28,L indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_29,15.54165625,-26.1188,3.747598125,0,0,0,1,1,1,0,29,R ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_30,-15.87663125,-25.64653125,3.335800625,0,0,0,1,1,1,0,30,L ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_31,4.974789375,12.44625,2.46409125,0,0,0,1,1,1,0,31,R olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_32,-5.724045,12.52948125,2.37324875,0,0,0,1,1,1,0,32,L olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 diff --git a/afidsvalidator/afids-templates/macaca/tpl-NMTv2.0asym_afids.fcsv b/afidsvalidator/afids-templates/macaca/tpl-NMTv2.0asym_afids.fcsv new file mode 100644 index 00000000..67fca31d --- /dev/null +++ b/afidsvalidator/afids-templates/macaca/tpl-NMTv2.0asym_afids.fcsv @@ -0,0 +1,35 @@ +# Markups fiducial file version = 4.6 +# CoordinateSystem = 0 +# columns = id,x,y,z,ow,ox,oy,oz,vis,sel,lock,label,desc,associatedNodeID +vtkMRMLMarkupsFiducialNode_0,0.017712306194739003,19.487752704941716,15.314483484676307,0.0,0.0,0.0,1.0,1,1,0,1,AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_1,0.02507324150872536,6.5001968692204875,14.470492570396765,0.0,0.0,0.0,1.0,1,1,0,2,PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_8,0.06442593327277103,-0.15965139217043003,10.375316818009642,0.0,0.0,0.0,1.0,1,1,0,3,infracollicular sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_9,0.09695604666688457,9.265816164861734,4.983816818009642,0.0,0.0,0.0,1.0,1,1,0,4,PMJ,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_10,0.07145481432352847,11.758029209924914,9.373650151342977,0.0,0.0,0.0,1.0,1,1,0,5,superior interpeduncular fossa,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_11,6.977348200500579,5.378365350001412,9.44973348467631,0.0,0.0,0.0,1.0,1,1,0,6,R superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_12,-6.800657625097212,5.4475541657561415,9.42148348467631,0.0,0.0,0.0,1.0,1,1,0,7,L superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_13,6.74008527933924,5.298340724688141,5.314084929890324,0.0,0.0,0.0,1.0,1,1,0,8,R inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_14,-6.590634602624992,5.402942753646125,5.264310044425934,0.0,0.0,0.0,1.0,1,1,0,9,L inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_15,0.08141666666666672,-7.8352608496132605,17.54030945183531,0.0,0.0,0.0,1.0,1,1,0,10,culmen,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_16,0.07717123538604066,14.65491039017895,8.210161231445943,0.0,0.0,0.0,1.0,1,1,0,11,intermammillary sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_17,1.2688402122617857,14.13169514231175,8.943494564779277,0.0,0.0,0.0,1.0,1,1,0,12,R MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_18,-1.117837406615059,14.117983365304875,8.929161231445944,0.0,0.0,0.0,1.0,1,1,0,13,L MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_19,0.05658861845621968,3.069807485816424,15.839583333333332,0.0,0.0,0.0,1.0,1,1,0,14,PG,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_20,4.451996843451092,18.8782419601866,24.61933333333333,0.0,0.0,0.0,1.0,1,1,0,15,R LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_21,-4.11949706399852,18.831834104060285,24.669583333333332,0.0,0.0,0.0,1.0,1,1,0,16,L LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_22,7.547715764277959,5.965671638768311,22.936416666666663,0.0,0.0,0.0,1.0,1,1,0,17,R LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_23,-7.217390318508649,5.8615400434078255,22.933583333333335,0.0,0.0,0.0,1.0,1,1,0,18,L LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_24,0.051701710089667834,29.771102742966722,23.20975,0.0,0.0,0.0,1.0,1,1,0,19,genu of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_25,0.048807124904610644,2.3809993316120925,16.91342172091821,0.0,0.0,0.0,1.0,1,1,0,20,splenium of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_26,13.630206738735046,18.951922956490428,1.9276682056104553,0.0,0.0,0.0,1.0,1,1,0,21,R AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_27,-13.453007880555313,19.043484620942216,1.8324182056104552,0.0,0.0,0.0,1.0,1,1,0,22,L AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_28,7.7781795356474355,15.847431906184726,5.643083333333332,0.0,0.0,0.0,1.0,1,1,0,23,R superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_29,-7.621876358066017,15.76534380988375,5.649249999999999,0.0,0.0,0.0,1.0,1,1,0,24,L superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_30,8.864692140485749,18.495101897673837,2.1042732334634047,0.0,0.0,0.0,1.0,1,1,0,25,R inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_31,-8.559627961778657,18.4638541363551,2.0792962441972,0.0,0.0,0.0,1.0,1,1,0,26,L inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_32,8.991028224369595,-0.7428333418601726,16.278961914111196,0.0,0.0,0.0,1.0,1,1,0,27,R indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_33,-8.56842220766469,-0.8226484996903669,16.40748864754982,0.0,0.0,0.0,1.0,1,1,0,28,L indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_34,15.755055460105135,-5.730513345214814,13.43473864754982,0.0,0.0,0.0,1.0,1,1,0,29,R ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_35,-15.440053436467146,-5.509345111742168,13.630988647549819,0.0,0.0,0.0,1.0,1,1,0,30,L ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_36,5.245529717783376,31.16699076681327,20.75807198088315,0.0,0.0,0.0,1.0,1,1,0,31,R olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_37,-5.4082911727647485,31.158702247293167,20.80748864754982,0.0,0.0,0.0,1.0,1,1,0,32,L olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 diff --git a/afidsvalidator/afids-templates/macaca/tpl-Yerkes19_afids.fcsv b/afidsvalidator/afids-templates/macaca/tpl-Yerkes19_afids.fcsv new file mode 100644 index 00000000..1217839c --- /dev/null +++ b/afidsvalidator/afids-templates/macaca/tpl-Yerkes19_afids.fcsv @@ -0,0 +1,35 @@ +# Markups fiducial file version = 4.6 +# CoordinateSystem = 0 +# columns = id,x,y,z,ow,ox,oy,oz,vis,sel,lock,label,desc,associatedNodeID +vtkMRMLMarkupsFiducialNode_1,-0.44425,-0.3698125,0.74,0,0,0,1,1,1,0,1,AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_2,-0.4267771875,-14.1443125,0.6506348125,0,0,0,1,1,1,0,2,PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_3,-0.4103589375,-19.72289375,-3.428631875,0,0,0,1,1,1,0,3,infracollicular sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_4,-0.41825,-9.8081875,-9.2228125,0,0,0,1,1,1,0,4,PMJ,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_5,-0.4371716875,-7.882514375,-4.486480625,0,0,0,1,1,1,0,5,superior interpeduncular fossa,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_6,6.6565,-14.3133125,-4.7779375,0,0,0,1,1,1,0,6,R superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_7,-7.6025,-14.3045625,-4.8665625,0,0,0,1,1,1,0,7,L superior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_8,6.5045625,-14.35225,-8.9871875,0,0,0,1,1,1,0,8,R inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_9,-7.5005625,-14.4080625,-8.935125,0,0,0,1,1,1,0,9,L inferior LMS,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_10,-0.4625710625,-27.673775,2.92126,0,0,0,1,1,1,0,10,culmen,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_11,-0.5190650625,-5.25716625,-5.947925,0,0,0,1,1,1,0,11,intermammillary sulcus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_12,0.6485614375,-5.47547375,-5.70790625,0,0,0,1,1,1,0,12,R MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_13,-1.71992125,-5.5072525,-5.697660625,0,0,0,1,1,1,0,13,L MB,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_14,-0.4638439375,-18.2865625,1.763011875,0,0,0,1,1,1,0,14,pineal gland,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_15,2.6965,-0.329125,8.820625,0,0,0,1,1,1,0,15,R LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_16,-3.81675,-0.275625,8.870625,0,0,0,1,1,1,0,16,L LV at AC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_17,6.2923125,-14.04675,8.5334375,0,0,0,1,1,1,0,17,R LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_18,-7.172125,-14.0260625,8.579625,0,0,0,1,1,1,0,18,L LV at PC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_19,-0.432125,11.2950625,7.593,0,0,0,1,1,1,0,19,genu of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_20,-0.417125,-18.6766875,2.823375,0,0,0,1,1,1,0,20,splenium of CC,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_21,13.6163125,-1.793125,-13.138875,0,0,0,1,1,1,0,21,R AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_22,-14.70824375,-2.2890875,-12.69210625,0,0,0,1,1,1,0,22,L AL temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_23,7.392625,-4.0513125,-9.181875,0,0,0,1,1,1,0,23,R superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_24,-8.6914375,-4.4888125,-9.145375,0,0,0,1,1,1,0,24,L superior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_25,9.3619375,-2.6685625,-13.3648125,0,0,0,1,1,1,0,25,R inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_26,-10.905,-3.2800625,-13.1568125,0,0,0,1,1,1,0,26,L inferior AM temporal horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_27,6.880100625,-20.46729375,1.99231,0,0,0,1,1,1,0,27,R indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_28,-7.813145,-20.4593625,2.1077025,0,0,0,1,1,1,0,28,L indusium griseum origin,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_29,15.40296875,-23.8728125,-1.439950625,0,0,0,1,1,1,0,29,R ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_30,-15.9348125,-24.46655,-1.131631875,0,0,0,1,1,1,0,30,L ventral occipital horn,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_31,4.71014875,11.98429375,4.73296,0,0,0,1,1,1,0,31,R olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 +vtkMRMLMarkupsFiducialNode_32,-5.52772875,11.9167,4.754100625,0,0,0,1,1,1,0,32,L olfactory sulcal fundus,vtkMRMLScalarVolumeNode1 diff --git a/afidsvalidator/landmark_info.py b/afidsvalidator/landmark_info.py new file mode 100644 index 00000000..cfba38fb --- /dev/null +++ b/afidsvalidator/landmark_info.py @@ -0,0 +1,536 @@ +"""Anatomical descriptions and placement guidance for the 32 AFIDs landmarks.""" + +# Keys match the abbreviation used as the attribute name on the Afids object +# (i.e., EXPECTED_DESCS[i][-1]). +LANDMARK_INFO = { + "AC": { + "full_name": "Anterior Commissure", + "description": ( + "A white matter tract connecting the two temporal lobes, crossing " + "the midline at the base of the septum pellucidum." + ), + "key_features": ( + "On a midsagittal slice, look for a small hyperintense (bright) " + "bundle just anterior to the columns of the fornix and inferior " + "to the genu of the corpus callosum. The AC sits directly at the " + "midline where the lamina terminalis meets the anterior " + "commissure itself." + ), + "common_mistakes": ( + "Placing too posteriorly (confusing with the fornix columns) or " + "too superiorly (landing on the genu of CC). Stay at the " + "midline — any lateral offset is an error." + ), + }, + "PC": { + "full_name": "Posterior Commissure", + "description": ( + "A small white matter tract at the dorsal aspect of the cerebral " + "aqueduct, marking the posterior boundary of the third ventricle." + ), + "key_features": ( + "On midsagittal: find the aqueduct of Sylvius and trace it " + "superiorly to where it opens into the third ventricle. The PC " + "lies at this junction, just superior to the superior colliculi " + "and inferior to the habenular commissure." + ), + "common_mistakes": ( + "Placing on the habenular commissure (too superior) or on the " + "superior colliculi (too inferior and posterior)." + ), + }, + "ICS": { + "full_name": "Infracollicular Sulcus", + "description": ( + "The sulcus immediately inferior to the inferior colliculi on " + "the posterior surface of the midbrain." + ), + "key_features": ( + "On sagittal: identify the quadrigeminal plate (four bumps on " + "the dorsal midbrain). The ICS is the groove just below the " + "inferior colliculi, where the midbrain meets the superior " + "medullary velum." + ), + "common_mistakes": ( + "Confusing with the intercollicular sulcus (the groove between " + "superior and inferior colliculi). The ICS is inferior to both " + "pairs of colliculi." + ), + }, + "PMJ": { + "full_name": "Pontomedullary Junction", + "description": ( + "The anatomical boundary between the pons and the medulla " + "oblongata on the ventral brainstem." + ), + "key_features": ( + "On sagittal: the ventral pons has a characteristic bulge " + "(the basis pontis). The PMJ is where this bulge ends and " + "the more tapered medulla begins — look for the change in " + "ventral contour. On axial: the disappearance of the " + "transverse pontine fibres." + ), + "common_mistakes": ( + "Placing too superiorly (within the pons) or too inferiorly " + "(within the medulla). The junction is often subtler on " + "standard T1 — use multiple planes." + ), + }, + "SIPF": { + "full_name": "Superior Interpeduncular Fossa", + "description": ( + "The apex of the interpeduncular fossa, the CSF-filled space " + "between the cerebral peduncles on the ventral midbrain." + ), + "key_features": ( + "On coronal or axial: the interpeduncular fossa appears as a " + "dark (CSF) inverted V between the two cerebral peduncles. " + "Place at the most superior tip of this space, at the level " + "of the mammillary bodies." + ), + "common_mistakes": ( + "Placing at the midpoint of the fossa rather than its most " + "superior extent. Confirm on sagittal that placement is " + "superior to the pons." + ), + }, + "RSLMS": { + "full_name": "Right Superior Lateral Midbrain Sulcus", + "description": ( + "The sulcus at the superior lateral margin of the right " + "midbrain, at the midbrain–thalamus interface." + ), + "key_features": ( + "On axial at the level of the superior colliculi: identify " + "the lateral margin of the midbrain. The RSLMS is the groove " + "where the superior aspect of the right midbrain meets the " + "overlying thalamus/pulvinar." + ), + "common_mistakes": ( + "Placing on the midbrain surface rather than in the sulcal " + "fundus. Confirm the left–right placement by ensuring " + "symmetry with LSLMS." + ), + }, + "LSLMS": { + "full_name": "Left Superior Lateral Midbrain Sulcus", + "description": ( + "The sulcus at the superior lateral margin of the left " + "midbrain, at the midbrain–thalamus interface." + ), + "key_features": ( + "Mirror of RSLMS. On axial at the level of the superior " + "colliculi: the groove where the superior aspect of the left " + "midbrain meets the overlying thalamus/pulvinar." + ), + "common_mistakes": ( + "Placing on the midbrain surface rather than in the sulcal " + "fundus. Check bilateral symmetry with RSLMS." + ), + }, + "RILMS": { + "full_name": "Right Inferior Lateral Midbrain Sulcus", + "description": ( + "The sulcus at the inferior lateral margin of the right " + "midbrain, at the midbrain–pons interface." + ), + "key_features": ( + "On axial at the level of the inferior colliculi or superior " + "pons: the groove at the lateral inferior margin of the right " + "midbrain, where it blends with the superior pons." + ), + "common_mistakes": ( + "Confusing with RSLMS — RILMS is more inferior and anterior. " + "Use coronal plane to confirm the inferior extent." + ), + }, + "LILMS": { + "full_name": "Left Inferior Lateral Midbrain Sulcus", + "description": ( + "The sulcus at the inferior lateral margin of the left " + "midbrain, at the midbrain–pons interface." + ), + "key_features": ( + "Mirror of RILMS. On axial at the level of the inferior " + "colliculi: the groove at the lateral inferior margin of the " + "left midbrain." + ), + "common_mistakes": ( + "Confusing with LSLMS — LILMS is more inferior. Confirm " + "bilateral symmetry with RILMS." + ), + }, + "CUL": { + "full_name": "Culmen", + "description": ( + "The most superior point of the anterior lobe of the " + "cerebellar vermis (lobule IV/V)." + ), + "key_features": ( + "On midsagittal: follow the superior surface of the cerebellum " + "to its highest midline point. The culmen is the peak of the " + "anterior vermis, immediately posterior to the primary fissure." + ), + "common_mistakes": ( + "Placing on the declive (posterior to the primary fissure) " + "or on a lateral cerebellar hemisphere rather than the midline " + "vermis." + ), + }, + "IMS": { + "full_name": "Intermammillary Sulcus", + "description": ( + "The midpoint of the sulcus between the two mammillary bodies " + "on the inferior hypothalamus." + ), + "key_features": ( + "On coronal: identify the two round mammillary bodies just " + "posterior to the tuber cinereum. The IMS is placed at the " + "midpoint of the groove between them. On axial: two bright " + "dots separated by a narrow sulcus at the floor of the " + "diencephalon." + ), + "common_mistakes": ( + "Placing on one of the mammillary bodies rather than the " + "sulcus between them. The IMS must be at the midline." + ), + }, + "RMB": { + "full_name": "Right Mammillary Body", + "description": ( + "The right mammillary body, a posterior hypothalamic nucleus " + "involved in memory circuits." + ), + "key_features": ( + "On coronal: the right of the two round structures at the " + "floor of the diencephalon, just anterior to the midbrain. " + "On axial: appears as a bright dot just right of midline, " + "posterior to the tuber cinereum." + ), + "common_mistakes": ( + "Placing on the IMS midpoint instead of the centre of the " + "right body, or landing too superiorly in the hypothalamus." + ), + }, + "LMB": { + "full_name": "Left Mammillary Body", + "description": ( + "The left mammillary body, a posterior hypothalamic nucleus " + "involved in memory circuits." + ), + "key_features": ( + "Mirror of RMB. On coronal: the left of the two round " + "structures at the floor of the diencephalon." + ), + "common_mistakes": ( + "Placing on the IMS midpoint instead of the centre of the " + "left body, or landing too superiorly in the hypothalamus." + ), + }, + "PG": { + "full_name": "Pineal Gland", + "description": ( + "A small midline neuroendocrine gland at the posterior roof " + "of the third ventricle." + ), + "key_features": ( + "On midsagittal: posterior to the habenular commissure and " + "superior to the superior colliculi. Often appears as a " + "calcified (hyperdense on CT, variable on MRI) nodule. " + "Place at the centre of the gland." + ), + "common_mistakes": ( + "Confusing with the habenular commissure (too anterior/superior) " + "or placing on the superior colliculi (too inferior). The PG " + "sits in the pineal recess, not on the quadrigeminal plate." + ), + }, + "RLVAC": { + "full_name": "Right Lateral Ventricle at AC", + "description": ( + "The most lateral point of the right lateral ventricle body " + "at the coronal level of the anterior commissure." + ), + "key_features": ( + "On a coronal slice through the AC: find the body of the " + "right lateral ventricle and place at its most lateral " + "extent. The septum pellucidum separates left and right." + ), + "common_mistakes": ( + "Using the wrong coronal level — must be at the AC, not " + "anterior or posterior to it. Confirm AC location on sagittal " + "first, then switch to coronal." + ), + }, + "LLVAC": { + "full_name": "Left Lateral Ventricle at AC", + "description": ( + "The most lateral point of the left lateral ventricle body " + "at the coronal level of the anterior commissure." + ), + "key_features": ( + "Mirror of RLVAC. On coronal at AC level: most lateral " + "extent of the left lateral ventricle body." + ), + "common_mistakes": ( + "Same as RLVAC — confirm AC level on sagittal first. " + "Check bilateral symmetry." + ), + }, + "RLVPC": { + "full_name": "Right Lateral Ventricle at PC", + "description": ( + "The most lateral point of the right lateral ventricle body " + "at the coronal level of the posterior commissure." + ), + "key_features": ( + "On a coronal slice through the PC: the right lateral " + "ventricle body at its most lateral point. The ventricle " + "is typically narrower here than at the AC level." + ), + "common_mistakes": ( + "Confusing the PC level with the AC level. Identify PC on " + "sagittal first (dorsal aqueduct opening), then move to " + "coronal." + ), + }, + "LLVPC": { + "full_name": "Left Lateral Ventricle at PC", + "description": ( + "The most lateral point of the left lateral ventricle body " + "at the coronal level of the posterior commissure." + ), + "key_features": ( + "Mirror of RLVPC. Coronal at PC level: most lateral extent " + "of the left lateral ventricle." + ), + "common_mistakes": ( + "Same as RLVPC — confirm PC level before switching planes. " + "Check bilateral symmetry." + ), + }, + "GENU": { + "full_name": "Genu of the Corpus Callosum", + "description": ( + "The anteriormost bend of the corpus callosum where it " + "curves inferiorly toward the rostrum." + ), + "key_features": ( + "On midsagittal: the anterior end of the corpus callosum " + "where the fibres curve forward and downward. Place at the " + "most anterior and inferior point of this bend, not at the " + "superior surface." + ), + "common_mistakes": ( + "Placing on the superior surface of the CC rather than the " + "anterior-inferior curve, or confusing with the rostrum " + "(the thin portion below the genu)." + ), + }, + "SPLE": { + "full_name": "Splenium of the Corpus Callosum", + "description": ( + "The posterior thickened end of the corpus callosum, " + "connecting the occipital and parietal lobes." + ), + "key_features": ( + "On midsagittal: the bulbous posterior terminus of the " + "corpus callosum. Place at the most posterior point of " + "the splenium, at the midline." + ), + "common_mistakes": ( + "Placing too anteriorly (on the posterior body rather than " + "the splenium), or laterally off the midline." + ), + }, + "RALTH": { + "full_name": "Right Anterolateral Temporal Horn", + "description": ( + "The anterolateral tip of the right temporal horn of the " + "lateral ventricle." + ), + "key_features": ( + "On axial or coronal: follow the temporal horn anteriorly " + "until it terminates. Place at the most anterior and lateral " + "extent of the CSF-filled horn." + ), + "common_mistakes": ( + "Placing within the horn rather than at its tip, or " + "confusing the choroid fissure with the horn lumen." + ), + }, + "LALTH": { + "full_name": "Left Anterolateral Temporal Horn", + "description": ( + "The anterolateral tip of the left temporal horn of the " + "lateral ventricle." + ), + "key_features": ( + "Mirror of RALTH. Axial or coronal: most anterior and " + "lateral extent of the left temporal horn CSF space." + ), + "common_mistakes": ( + "Placing within the horn body rather than at its anterior " + "tip. Check bilateral symmetry with RALTH." + ), + }, + "RSAMTH": { + "full_name": "Right Superior Anteromedial Temporal Horn", + "description": ( + "The superior anteromedial extent of the right temporal horn, " + "near the amygdala." + ), + "key_features": ( + "On coronal anterior to the hippocampal head: find the " + "superomedial corner of the temporal horn where it abuts " + "the amygdala. This is a tight, CSF-filled angle." + ), + "common_mistakes": ( + "Placing too laterally (on the anterolateral horn) or " + "confusing with RIAMTH below. RSAMTH is the superior corner." + ), + }, + "LSAMTH": { + "full_name": "Left Superior Anteromedial Temporal Horn", + "description": ( + "The superior anteromedial extent of the left temporal horn, " + "near the amygdala." + ), + "key_features": ( + "Mirror of RSAMTH. Coronal anterior to hippocampal head: " + "superomedial corner of the left temporal horn." + ), + "common_mistakes": ( + "Confusing with LIAMTH (inferior corner) or LALTH (lateral). " + "Check bilateral symmetry." + ), + }, + "RIAMTH": { + "full_name": "Right Inferior Anteromedial Temporal Horn", + "description": ( + "The inferior anteromedial extent of the right temporal horn, " + "near the hippocampal head." + ), + "key_features": ( + "On coronal at the hippocampal head: the inferomedial corner " + "of the right temporal horn where the horn curves around the " + "hippocampus. Inferior to RSAMTH in the same coronal plane." + ), + "common_mistakes": ( + "Placing on the hippocampal surface rather than in the " + "CSF-filled corner of the horn, or confusing with RSAMTH " + "(which is superior)." + ), + }, + "LIAMTH": { + "full_name": "Left Inferior Anteromedial Temporal Horn", + "description": ( + "The inferior anteromedial extent of the left temporal horn, " + "near the hippocampal head." + ), + "key_features": ( + "Mirror of RIAMTH. Coronal at hippocampal head: inferomedial " + "corner of the left temporal horn." + ), + "common_mistakes": ( + "Confusing with LSAMTH (superior corner). Verify by " + "checking RIAMTH for bilateral symmetry." + ), + }, + "RIGO": { + "full_name": "Right Indusium Griseum Origin", + "description": ( + "The origin of the right indusium griseum — a thin grey " + "matter strip on the superior surface of the corpus callosum " + "continuous with the dentate gyrus." + ), + "key_features": ( + "On sagittal: trace the superior surface of the genu of the " + "CC posteriorly. The RIGO is at the point where the indusium " + "griseum first appears on the right side, just posterior to " + "the genu on the CC surface." + ), + "common_mistakes": ( + "Placing on the CC body surface rather than at the origin " + "point, or confusing with the cingulate gyrus above." + ), + }, + "LIGO": { + "full_name": "Left Indusium Griseum Origin", + "description": ( + "The origin of the left indusium griseum on the superior " + "surface of the corpus callosum." + ), + "key_features": ( + "Mirror of RIGO. Sagittal: posterior to the genu on the " + "left surface of the CC where the indusium griseum begins." + ), + "common_mistakes": ( + "Same as RIGO — avoid placing on the cingulate gyrus or " + "mid-body of the CC." + ), + }, + "RVOH": { + "full_name": "Right Ventral Occipital Horn", + "description": ( + "The most ventral and posterior tip of the right occipital " + "horn of the lateral ventricle." + ), + "key_features": ( + "On axial: follow the occipital horn posteriorly to its " + "terminal point. Place at the most posterior–inferior " + "tip of the right CSF-filled horn." + ), + "common_mistakes": ( + "Placing mid-horn rather than at the terminal tip, or " + "including the calcar avis (the white matter bulge into " + "the occipital horn) as part of the CSF space." + ), + }, + "LVOH": { + "full_name": "Left Ventral Occipital Horn", + "description": ( + "The most ventral and posterior tip of the left occipital " + "horn of the lateral ventricle." + ), + "key_features": ( + "Mirror of RVOH. Axial: most posterior–inferior tip of the " + "left occipital horn." + ), + "common_mistakes": ( + "Same as RVOH. Check bilateral symmetry with RVOH." + ), + }, + "ROSF": { + "full_name": "Right Olfactory Sulcal Fundus", + "description": ( + "The deepest point of the right olfactory sulcus on the " + "orbital (inferior) surface of the right frontal lobe." + ), + "key_features": ( + "On coronal through the frontal lobe: the olfactory sulcus " + "is a vertical groove on the orbital surface housing the " + "olfactory tract. Place at the deepest point (fundus) of " + "this sulcus on the right side." + ), + "common_mistakes": ( + "Placing on the olfactory tract itself rather than the " + "sulcal fundus, or confusing with the medial orbital sulcus." + ), + }, + "LOSF": { + "full_name": "Left Olfactory Sulcal Fundus", + "description": ( + "The deepest point of the left olfactory sulcus on the " + "orbital surface of the left frontal lobe." + ), + "key_features": ( + "Mirror of ROSF. Coronal: deepest point of the left " + "olfactory sulcus on the orbital frontal surface." + ), + "common_mistakes": ( + "Same as ROSF — check bilateral symmetry and use the " + "olfactory tract as a guide to find the sulcus." + ), + }, +} diff --git a/afidsvalidator/static/lib/afidsvalidator-react/styles/afids_custom.css b/afidsvalidator/static/lib/afidsvalidator-react/styles/afids_custom.css index 1e50f259..ddccf09c 100644 --- a/afidsvalidator/static/lib/afidsvalidator-react/styles/afids_custom.css +++ b/afidsvalidator/static/lib/afidsvalidator-react/styles/afids_custom.css @@ -1,26 +1,59 @@ -:root { - /* Global colours */ - --afids-green: #00ff01; - --dark: #000; - --light: #fff; +/* ===================================================================== + AFIDs Validator — Design System + ===================================================================== */ +@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Space+Mono:wght@400;700&family=Inter:wght@300;400;500;600&display=swap'); - /* Fonts */ - --nav-font: 'Bebas Neue', sans-serif; - --nav-fontsize: 36px; - --def-font: "Roboto", sans-serif; - --def-fontsize: 20px; - --foot-font: "Roboto", sans-serif; - --foot-fontsize: 16px; +:root { + --green: #00ff01; + --green-dim: rgba(0, 255, 1, 0.12); + --green-mid: rgba(0, 255, 1, 0.35); + --green-glow: 0 0 14px rgba(0, 255, 1, 0.45); + --green-glow-lg: 0 0 30px rgba(0, 255, 1, 0.3), 0 0 60px rgba(0, 255, 1, 0.1); + --dark: #080808; + --dark-card: #101010; + --dark-raised: #181818; + --dark-border: #222; + --light: #f0f0f0; + --muted: #888; + --warning: #ffaa00; + --danger: #ff4040; + --nav-font: 'Bebas Neue', sans-serif; + --mono-font: 'Space Mono', monospace; + --body-font: 'Inter', sans-serif; + --radius: 6px; + --radius-lg: 12px; + --transition: all 0.22s ease; } +/* ── Reset & Base ──────────────────────────────────────────────────── */ +*, *::before, *::after { box-sizing: border-box; } + html, body { max-width: 100vw; margin: 0; padding: 0; background-color: var(--dark); color: var(--light); - font-family: var(--def-font); - font-size: var(--def-fontsize); + font-family: var(--body-font); + font-size: 16px; + line-height: 1.6; + -webkit-font-smoothing: antialiased; +} + +/* subtle scanline overlay — gives scientific terminal feel */ +body::after { + content: ''; + position: fixed; + inset: 0; + background: repeating-linear-gradient( + 0deg, + transparent, + transparent 2px, + rgba(0, 0, 0, 0.03) 2px, + rgba(0, 0, 0, 0.03) 4px + ); + pointer-events: none; + z-index: 9998; } .container { @@ -28,74 +61,829 @@ html, body { flex-direction: column; min-height: 100vh; background-color: var(--dark); - color: var(--light); - font-size: var(--def-fontsize); } main { flex: 1; + padding: 2rem 0; } -a { - color: var(--afids-green); +a { color: var(--green); transition: var(--transition); } +a:hover { color: var(--light); text-decoration: none; } + +/* ── Keyframe animations ───────────────────────────────────────────── */ +@keyframes glow-pulse { + 0%, 100% { box-shadow: 0 0 8px rgba(0,255,1,0.3); } + 50% { box-shadow: 0 0 24px rgba(0,255,1,0.7); } } -a:hover { - color: var(--light); +@keyframes fade-in-up { + from { opacity: 0; transform: translateY(24px); } + to { opacity: 1; transform: translateY(0); } +} + +@keyframes slide-in-left { + from { opacity: 0; transform: translateX(-20px); } + to { opacity: 1; transform: translateX(0); } +} + +@keyframes border-spin { + to { --angle: 360deg; } +} + +@keyframes flicker { + 0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% { opacity: 1; } + 20%, 24%, 55% { opacity: 0.92; } +} + +@keyframes count-up { + from { opacity: 0; transform: scale(0.85); } + to { opacity: 1; transform: scale(1); } +} + +/* ── Navbar ────────────────────────────────────────────────────────── */ +#react-navbar { + position: sticky; + top: 0; + z-index: 1000; + background: rgba(8, 8, 8, 0.97); + backdrop-filter: blur(8px); + border-bottom: 1px solid var(--dark-border); +} + +#afids-banner { + width: clamp(360px, 55vw, 620px); + margin: 1.4rem auto 0.6rem; + display: block; + filter: drop-shadow(var(--green-glow)); } -/* Navbar */ a.nav-link { - padding: 0 50px !important; + padding: 0 2rem !important; text-transform: uppercase; text-align: center; - color: var(--light) !important; + color: var(--muted) !important; font-family: var(--nav-font); - font-size: var(--nav-fontsize); + font-size: 1.5rem; + letter-spacing: 0.05em; + transition: var(--transition); + position: relative; +} + +a.nav-link::after { + content: ''; + position: absolute; + bottom: -2px; + left: 50%; + right: 50%; + height: 2px; + background: var(--green); + transition: var(--transition); } +a.nav-link:hover, +a.nav-link.active, a.active { - color: var(--afids-green) !important; + color: var(--green) !important; + text-shadow: 0 0 8px rgba(0,255,1,0.5); } -a.nav-link:hover { - color: var(--afids-green) !important; +a.nav-link:hover::after, +a.active::after { + left: 10%; + right: 10%; } .nav-hr { - color: var(--afids-green); - margin-top: 0; - border-top: 0.2vw solid; + color: var(--green); + margin: 0; + border: none; + border-top: 1px solid var(--green); + box-shadow: var(--green-glow); } -/* Footer */ +/* ── Footer ────────────────────────────────────────────────────────── */ footer { display: flex; flex-direction: column; align-items: center; justify-content: center; - background-color: var(--afids-green); - color: var(--dark); - font-size: var(--foot-fontsize); + background-color: var(--dark-card); + border-top: 1px solid var(--dark-border); + color: var(--muted); + font-size: 0.85rem; + padding: 1.2rem; + font-family: var(--mono-font); +} + +footer a { color: var(--green); } +footer a:hover { color: var(--light); } + +.footIcon { + width: 20px; + height: 20px; + margin: 6px; + transition: var(--transition); } -footer a { +.footIcon:hover { filter: drop-shadow(0 0 6px var(--green)); } + +/* ── Typography ────────────────────────────────────────────────────── */ +h1, h2, h3, h4 { + font-family: var(--nav-font); + letter-spacing: 0.04em; +} + +.text-green { color: var(--green); } +.text-muted { color: var(--muted) !important; } +.text-warning { color: var(--warning); } +.text-danger { color: var(--danger); } +.text-mono { font-family: var(--mono-font); } + +.section-label { + font-family: var(--mono-font); + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.12em; + color: var(--green); + margin-bottom: 0.3rem; +} + +/* ── Cards ─────────────────────────────────────────────────────────── */ +.afids-card { + background: var(--dark-card); + border: 1px solid var(--dark-border); + border-radius: var(--radius-lg); + padding: 1.5rem; + transition: var(--transition); +} + +.afids-card:hover { + border-color: rgba(0,255,1,0.4); + box-shadow: var(--green-glow); +} + +.afids-card-accent { + border-left: 3px solid var(--green); + border-radius: 0 var(--radius-lg) var(--radius-lg) 0; +} + +/* ── Form controls ─────────────────────────────────────────────────── */ +.form-section-title { + font-family: var(--mono-font); + font-size: 0.72rem; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--green); + margin-bottom: 0.5rem; +} + +.afids-select { + width: 100%; + background: var(--dark-raised); + color: var(--light); + border: 1px solid var(--dark-border); + border-radius: var(--radius); + padding: 0.6rem 1rem; + font-family: var(--body-font); + font-size: 0.95rem; + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2300ff01' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 0.8rem center; + transition: var(--transition); + cursor: pointer; +} + +.afids-select:focus { + outline: none; + border-color: var(--green); + box-shadow: 0 0 0 2px var(--green-dim), var(--green-glow); +} + +.afids-select option { background: var(--dark-raised); } + +/* File upload zone */ +.file-drop-zone { + border: 2px dashed var(--dark-border); + border-radius: var(--radius-lg); + padding: 2.5rem 1rem; + text-align: center; + cursor: pointer; + transition: var(--transition); + position: relative; + background: var(--dark-card); +} + +.file-drop-zone:hover, +.file-drop-zone.dragover { + border-color: var(--green); + background: var(--green-dim); + box-shadow: var(--green-glow); +} + +.file-drop-zone input[type="file"] { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + opacity: 0; + cursor: pointer; +} + +.file-drop-icon { + font-size: 2.5rem; + margin-bottom: 0.5rem; + display: block; + color: var(--green); + opacity: 0.7; +} + +.file-drop-text { + font-family: var(--mono-font); + font-size: 0.85rem; + color: var(--muted); + margin: 0; +} + +.file-drop-text strong { + color: var(--light); +} + +#filename-display { + margin-top: 0.5rem; + font-family: var(--mono-font); + font-size: 0.8rem; + color: var(--green); + min-height: 1.2em; +} + +/* Checkbox */ +.afids-checkbox-row { + display: flex; + align-items: center; + gap: 0.6rem; + margin: 0.8rem 0; +} + +.afids-checkbox-row input[type="checkbox"] { + accent-color: var(--green); + width: 16px; + height: 16px; + cursor: pointer; +} + +.afids-checkbox-row label { + font-size: 0.88rem; + color: var(--muted); + cursor: pointer; + margin: 0; +} + +/* Submit button */ +.btn-afids { + display: inline-block; + background: transparent; + color: var(--green); + border: 2px solid var(--green); + border-radius: var(--radius); + padding: 0.65rem 2.5rem; + font-family: var(--nav-font); + font-size: 1.4rem; + letter-spacing: 0.12em; + cursor: pointer; + transition: var(--transition); + position: relative; + overflow: hidden; +} + +.btn-afids::before { + content: ''; + position: absolute; + inset: 0; + background: var(--green); + transform: translateX(-101%); + transition: transform 0.28s ease; + z-index: 0; +} + +.btn-afids span { position: relative; z-index: 1; } + +.btn-afids:hover { color: var(--dark); + box-shadow: var(--green-glow); + animation: glow-pulse 1.4s ease-in-out infinite; +} + +.btn-afids:hover::before { transform: translateX(0); } + +/* ── Result alert ───────────────────────────────────────────────────── */ +.afids-alert { + border-radius: var(--radius); + padding: 0.9rem 1.2rem; + font-family: var(--mono-font); + font-size: 0.9rem; + border: 1px solid transparent; + animation: fade-in-up 0.4s ease both; +} + +.afids-alert-success { + background: rgba(0, 255, 1, 0.08); + border-color: rgba(0, 255, 1, 0.4); + color: var(--green); +} + +.afids-alert-danger { + background: rgba(255, 64, 64, 0.08); + border-color: rgba(255, 64, 64, 0.4); + color: var(--danger); +} + +/* ── Session summary dashboard ─────────────────────────────────────── */ +.summary-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: 1rem; + margin: 1.5rem 0; + animation: fade-in-up 0.5s ease both; +} + +.summary-stat { + background: var(--dark-card); + border: 1px solid var(--dark-border); + border-radius: var(--radius-lg); + padding: 1rem 1.2rem; + text-align: center; + transition: var(--transition); +} + +.summary-stat:hover { + border-color: rgba(0,255,1,0.3); + box-shadow: var(--green-glow); + transform: translateY(-2px); } -footer a:hover { +.summary-stat-value { + font-family: var(--mono-font); + font-size: 1.8rem; + font-weight: 700; + line-height: 1.1; color: var(--light); + animation: count-up 0.5s ease both; } -.footIcon { - width: var(--def-fontsize); - height: var(--def-fontsize); - margin: 8px; +.summary-stat-sub { + font-family: var(--mono-font); + font-size: 0.75rem; + color: var(--muted); + margin-top: 0.1rem; +} + +.summary-stat-label { + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--muted); + margin-top: 0.4rem; + font-family: var(--mono-font); +} + +.stat-green { color: var(--green); } +.stat-red { color: var(--danger); } +.stat-yellow { color: var(--warning); } + +/* ── Tabs ───────────────────────────────────────────────────────────── */ +.afids-tabs { + display: flex; + gap: 0; + border-bottom: 1px solid var(--dark-border); + margin-bottom: 1.5rem; +} + +.afids-tabs .nav-link { + font-family: var(--mono-font) !important; + font-size: 0.8rem !important; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--muted) !important; + padding: 0.6rem 1.4rem !important; + border: 1px solid transparent; + border-bottom: none; + border-radius: var(--radius) var(--radius) 0 0; + transition: var(--transition); +} + +.afids-tabs .nav-link:hover { + color: var(--light) !important; + background: var(--dark-raised); + text-shadow: none; +} + +.afids-tabs .nav-link.active, +.afids-tabs .nav-link[aria-selected="true"] { + color: var(--green) !important; + background: var(--dark-card); + border-color: var(--dark-border); + border-bottom-color: var(--dark-card); + text-shadow: 0 0 8px rgba(0,255,1,0.4); +} + +.afids-tabs .nav-link::after { display: none; } + +/* ── Distance table ─────────────────────────────────────────────────── */ +.afids-table { + width: 100%; + border-collapse: separate; + border-spacing: 0; + font-family: var(--mono-font); + font-size: 0.82rem; +} + +.afids-table thead th { + padding: 0.6rem 0.9rem; + text-transform: uppercase; + letter-spacing: 0.08em; + font-size: 0.7rem; + color: var(--muted); + border-bottom: 1px solid var(--dark-border); + background: var(--dark-card); + white-space: nowrap; +} + +.afids-table tbody tr { + border-bottom: 1px solid var(--dark-border); + transition: var(--transition); +} + +.afids-table tbody tr:hover { + background: var(--dark-raised); +} + +.afids-table td { + padding: 0.5rem 0.9rem; + vertical-align: middle; +} + +.afids-table .label-cell { + font-weight: 700; + color: var(--light); + white-space: nowrap; +} + +.afids-table .dist-excellent { color: var(--green); } +.afids-table .dist-good { color: #aaff00; } +.afids-table .dist-warning { color: var(--warning); } +.afids-table .dist-danger { color: var(--danger); } +.afids-table .dir-cell { color: var(--muted); font-size: 0.78rem; } + +/* ── Teaching cards ─────────────────────────────────────────────────── */ +.teaching-section-header { + display: flex; + align-items: center; + gap: 1rem; + margin: 2.5rem 0 1rem; +} + +.teaching-section-header h3 { + font-family: var(--mono-font); + font-size: 0.85rem; + text-transform: uppercase; + letter-spacing: 0.12em; + color: var(--green); + margin: 0; +} + +.teaching-section-header hr { + flex: 1; + border: none; + border-top: 1px solid var(--dark-border); + margin: 0; +} + +.teaching-card { + background: var(--dark-card); + border: 1px solid var(--dark-border); + border-left: 3px solid var(--green); + border-radius: 0 var(--radius-lg) var(--radius-lg) 0; + padding: 1.2rem 1.4rem; + margin-bottom: 1rem; + animation: slide-in-left 0.4s ease both; + transition: var(--transition); +} + +.teaching-card:hover { + border-color: rgba(0,255,1,0.5); + border-left-color: var(--green); + box-shadow: var(--green-glow); +} + +.teaching-card-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + flex-wrap: wrap; + gap: 0.5rem; + margin-bottom: 0.8rem; +} + +.teaching-card-title { + font-family: var(--mono-font); + font-size: 0.95rem; + font-weight: 700; + color: var(--green); + margin: 0; +} + +.teaching-card-abbr { + background: var(--green-dim); + color: var(--green); + border: 1px solid rgba(0,255,1,0.3); + border-radius: 3px; + padding: 0 0.4rem; + font-size: 0.8rem; + font-family: var(--mono-font); + margin-right: 0.5rem; +} + +.teaching-card-error { + font-family: var(--mono-font); + font-size: 0.9rem; + white-space: nowrap; +} + +.teaching-card-body p { + font-size: 0.88rem; + color: #ccc; + margin: 0 0 0.6rem; + line-height: 1.55; +} + +.teaching-card-sub-label { + font-family: var(--mono-font); + font-size: 0.65rem; + text-transform: uppercase; + letter-spacing: 0.1em; + margin-bottom: 0.25rem; + display: block; +} + +.sub-label-green { color: var(--green); } +.sub-label-yellow { color: var(--warning); } + +/* ── Hero (index page) ──────────────────────────────────────────────── */ +.hero { + padding: 4rem 0 3rem; + text-align: center; +} + +.hero-kicker { + font-family: var(--mono-font); + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.2em; + color: var(--green); + margin-bottom: 1rem; + display: block; +} + +.hero-title { + font-family: var(--nav-font); + font-size: clamp(2.5rem, 6vw, 4.5rem); + letter-spacing: 0.06em; + line-height: 1.05; + margin-bottom: 1.2rem; + color: var(--light); + text-shadow: 0 0 40px rgba(0,255,1,0.15); +} + +.hero-title .accent { + color: var(--green); + text-shadow: 0 0 20px rgba(0,255,1,0.6); + animation: flicker 6s linear infinite; +} + +.hero-subtitle { + font-size: 1.05rem; + color: var(--muted); + max-width: 580px; + margin: 0 auto 2.5rem; + line-height: 1.7; +} + +.hero-stats { + display: flex; + justify-content: center; + gap: 3rem; + margin: 2.5rem 0; + flex-wrap: wrap; +} + +.hero-stat-value { + font-family: var(--mono-font); + font-size: 2.5rem; + font-weight: 700; + color: var(--green); + display: block; + line-height: 1; + text-shadow: var(--green-glow); +} + +.hero-stat-label { + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--muted); + margin-top: 0.3rem; + font-family: var(--mono-font); +} + +.hero-divider { + width: 60px; + height: 2px; + background: linear-gradient(90deg, transparent, var(--green), transparent); + margin: 2rem auto; + box-shadow: var(--green-glow); +} + +/* Feature grid */ +.feature-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + margin: 2rem 0; +} + +.feature-card { + background: var(--dark-card); + border: 1px solid var(--dark-border); + border-radius: var(--radius-lg); + padding: 1.4rem 1.2rem; + text-align: left; + transition: var(--transition); +} + +.feature-card:hover { + border-color: rgba(0,255,1,0.35); + transform: translateY(-3px); + box-shadow: var(--green-glow); +} + +.feature-icon { + font-size: 1.5rem; + margin-bottom: 0.6rem; + display: block; +} + +.feature-title { + font-family: var(--mono-font); + font-size: 0.82rem; + font-weight: 700; + color: var(--light); + text-transform: uppercase; + letter-spacing: 0.06em; + margin-bottom: 0.4rem; +} + +.feature-desc { + font-size: 0.82rem; + color: var(--muted); + line-height: 1.5; + margin: 0; +} + +/* Video panel */ +.video-panel { + border: 1px solid var(--dark-border); + border-radius: var(--radius-lg); + overflow: hidden; + box-shadow: 0 0 40px rgba(0,0,0,0.6); + transition: var(--transition); +} + +.video-panel:hover { + border-color: rgba(0,255,1,0.3); + box-shadow: var(--green-glow); } #afidsVideo { - width: 90%; - height: width / (16 / 9); - border: var(--light) solid 1px; - margin-bottom: 16px; -} \ No newline at end of file + width: 100%; + display: block; + margin: 0; + border: none; +} + +/* ── Validator form page ────────────────────────────────────────────── */ +.page-header { + padding: 1.5rem 0 1rem; + border-bottom: 1px solid var(--dark-border); + margin-bottom: 2rem; +} + +.page-header h1 { + font-size: clamp(1.8rem, 4vw, 2.5rem); + margin: 0; + color: var(--light); +} + +.page-header p { + color: var(--muted); + margin: 0.4rem 0 0; + font-size: 0.9rem; +} + +/* Two-column form layout */ +.form-row-cols { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; + margin-bottom: 1.2rem; +} + +@media (max-width: 600px) { + .form-row-cols { grid-template-columns: 1fr; } + .hero-stats { gap: 2rem; } +} + +/* ── Misc utility ───────────────────────────────────────────────────── */ +.green-rule { + border: none; + border-top: 1px solid var(--green); + box-shadow: var(--green-glow); + margin: 1.5rem 0; + opacity: 0.6; +} + +.fade-in { animation: fade-in-up 0.5s ease both; } +.fade-in-2 { animation: fade-in-up 0.5s ease 0.1s both; } +.fade-in-3 { animation: fade-in-up 0.5s ease 0.2s both; } + +/* ── Login page ─────────────────────────────────────────────────────── */ +.login-wrap { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 40vh; + gap: 1.5rem; +} + +.login-heading { + font-family: var(--mono-font); + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.15em; + color: var(--muted); +} + +.btn-orcid { + display: flex; + align-items: center; + gap: 0.9rem; + background: var(--dark-card); + border: 1px solid var(--dark-border); + border-radius: var(--radius-lg); + padding: 0.9rem 1.8rem; + color: var(--light); + font-family: var(--body-font); + font-size: 1rem; + font-weight: 500; + text-decoration: none; + transition: var(--transition); + cursor: pointer; +} + +.btn-orcid:hover { + border-color: var(--green); + box-shadow: var(--green-glow); + color: var(--light); + transform: translateY(-2px); +} + +.btn-orcid img { width: 32px; height: 32px; } + +/* ── Contact page ───────────────────────────────────────────────────── */ +.contact-card { + background: var(--dark-card); + border: 1px solid var(--dark-border); + border-radius: var(--radius-lg); + padding: 2rem; + max-width: 640px; +} + +.contact-card p { + color: #bbb; + font-size: 0.95rem; + line-height: 1.7; +} + +.contact-card a { + color: var(--green); + text-decoration: underline; + text-underline-offset: 3px; + text-decoration-color: rgba(0,255,1,0.4); +} + +.contact-card a:hover { + color: var(--light); + text-decoration-color: var(--light); +} diff --git a/afidsvalidator/templates/app.html b/afidsvalidator/templates/app.html index d01756c7..9d3040b7 100644 --- a/afidsvalidator/templates/app.html +++ b/afidsvalidator/templates/app.html @@ -1,144 +1,233 @@ {% extends "base.html" %} -{% block title %} | VALIDATOR {% endblock %} +{% block title %} | Validator{% endblock %} {% block content %} -
Use the following form to compare user placed fiducials to one of the available templates!
-If you choose to "Upload to Database", fiducials from the file will be uploaded and stored. These - placements may be used in the future to identify fiducials users are having difficulty placing. -
-