11import DataTable from "../../components/DataTable" ;
2+ import CardContainer from "../../components/CardContainer" ;
3+
24import { DownloadIcon } from "../../components/Icons" ;
35import { omitGraphKeys } from "../../utils" ;
46
57// This could be extended to use the BZ visualiser from this data (if possible);
68// TODO - build a KPOINT converter that spits out VASP/QE formats
7- // TODO - See if this data is explicitily able to produce aiida BZ from the brillouin zone
89// TODO - move this from WIP...
10+
11+ // src/components/BZVisualizer.jsx
12+ import React , { useEffect , useRef } from "react" ;
13+ import { createBZVisualizer } from "brillouinzone-visualizer" ;
14+
15+ function BZVisualizer ( { data, options } ) {
16+ const containerRef = useRef ( null ) ;
17+
18+ useEffect ( ( ) => {
19+ if ( containerRef . current ) {
20+ containerRef . current . innerHTML = "" ;
21+ createBZVisualizer ( containerRef . current , data , options ) ;
22+ }
23+ } , [ data , options ] ) ;
24+
25+ return < div ref = { containerRef } style = { { width : "100%" , height : "400px" } } /> ;
26+ }
27+
28+ function reciprocalLattice ( cell ) {
29+ if ( ! cell || cell . length < 3 )
30+ return [
31+ [ 1 , 0 , 0 ] ,
32+ [ 0 , 1 , 0 ] ,
33+ [ 0 , 0 , 1 ] ,
34+ ] ;
35+
36+ const [ a1 , a2 , a3 ] = cell ;
37+
38+ const cross = ( u , v ) => [
39+ u [ 1 ] * v [ 2 ] - u [ 2 ] * v [ 1 ] ,
40+ u [ 2 ] * v [ 0 ] - u [ 0 ] * v [ 2 ] ,
41+ u [ 0 ] * v [ 1 ] - u [ 1 ] * v [ 0 ] ,
42+ ] ;
43+
44+ const dot = ( u , v ) => u [ 0 ] * v [ 0 ] + u [ 1 ] * v [ 1 ] + u [ 2 ] * v [ 2 ] ;
45+
46+ const volume = dot ( a1 , cross ( a2 , a3 ) ) ;
47+
48+ const b1 = cross ( a2 , a3 ) . map ( ( x ) => ( 2 * Math . PI * x ) / volume ) ;
49+ const b2 = cross ( a3 , a1 ) . map ( ( x ) => ( 2 * Math . PI * x ) / volume ) ;
50+ const b3 = cross ( a1 , a2 ) . map ( ( x ) => ( 2 * Math . PI * x ) / volume ) ;
51+
52+ return [ b1 , b2 , b3 ] ;
53+ }
54+
955export default function KpointsDataVisualiser ( { nodeData = { } } ) {
1056 const attributes = nodeData . attributes || { } ;
11- const derivedProperties = nodeData . derivedProperties || { } ;
57+ const derivedProperties = nodeData . derived_properties || { } ;
1258
1359 if ( ! attributes && ! derivedProperties ) {
1460 return < div > No attributes available</ div > ;
1561 }
1662
63+ // ----- Safe lattice extraction -----
64+ const lattice = attributes . cell
65+ ? {
66+ a : attributes . cell [ 0 ] ?. [ 0 ] ?? 0 ,
67+ b : attributes . cell [ 1 ] ?. [ 1 ] ?? 0 ,
68+ c : attributes . cell [ 2 ] ?. [ 2 ] ?? 0 ,
69+ }
70+ : null ;
71+ const numSites = attributes . cell ?. length || 0 ;
72+
73+ // ----- Bundle data for BZVisualizer -----
74+ const [ b1 , b2 , b3 ] = reciprocalLattice ( attributes . cell ) ;
75+
76+ const bzData = {
77+ ...derivedProperties ,
78+ b1,
79+ b2,
80+ b3,
81+ } ;
82+
83+ // ----- Reciprocal lattice table -----
84+ const recipColumns = [ "vector" , "x" , "y" , "z" ] ;
85+ const recipData = [
86+ { vector : "b1" , x : b1 [ 0 ] , y : b1 [ 1 ] , z : b1 [ 2 ] } ,
87+ { vector : "b2" , x : b2 [ 0 ] , y : b2 [ 1 ] , z : b2 [ 2 ] } ,
88+ { vector : "b3" , x : b3 [ 0 ] , y : b3 [ 1 ] , z : b3 [ 2 ] } ,
89+ ] ;
90+
1791 // ----- Cell table -----
1892 const cellColumns = [ "x" , "y" , "z" ] ;
1993 const cellData = ( attributes . cell || [ ] ) . map ( ( row ) => ( {
20- x : row [ 0 ] ,
21- y : row [ 1 ] ,
22- z : row [ 2 ] ,
94+ x : row [ 0 ] ?? 0 ,
95+ y : row [ 1 ] ?? 0 ,
96+ z : row [ 2 ] ?? 0 ,
2397 } ) ) ;
2498
2599 // ----- Mesh table -----
26100 const meshColumns = [ "dimension" , "value" ] ;
27101 const meshData = ( attributes . mesh || [ ] ) . map ( ( val , idx ) => ( {
28102 dimension : idx + 1 ,
29- value : val ,
103+ value : val ?? 0 ,
30104 } ) ) ;
31105
32106 // ----- Offset table -----
33107 const offsetColumns = [ "i" , "x" , "y" , "z" ] ;
34108 const offsetData = ( attributes . offset || [ ] ) . map ( ( val , idx ) => ( {
35109 i : idx + 1 ,
36- x : val [ 0 ] ?? val ,
37- y : val [ 1 ] ?? 0 ,
38- z : val [ 2 ] ?? 0 ,
110+ x : Array . isArray ( val ) ? ( val [ 0 ] ?? 0 ) : ( val ?? 0 ) ,
111+ y : Array . isArray ( val ) ? ( val [ 1 ] ?? 0 ) : 0 ,
112+ z : Array . isArray ( val ) ? ( val [ 2 ] ?? 0 ) : 0 ,
39113 } ) ) ;
40114
41115 // ----- PBC table -----
@@ -44,62 +118,80 @@ export default function KpointsDataVisualiser({ nodeData = {} }) {
44118 . filter ( ( key ) => key in attributes )
45119 . map ( ( key ) => ( {
46120 axis : key ,
47- periodic : attributes [ key ] ? "True" : "False" ,
121+ periodic : ! ! attributes [ key ] ,
48122 } ) ) ;
49123
50124 // ----- ABS Kpoints table -----
51125 const kpointColumns = [ "K-point number" , "x" , "y" , "z" ] ;
52126 const kpointData = ( derivedProperties . explicit_kpoints_abs || [ ] ) . map (
53127 ( row , idx ) => ( {
54128 "K-point number" : idx + 1 ,
55- x : row [ 0 ] ,
56- y : row [ 1 ] ,
57- z : row [ 2 ] ,
129+ x : row [ 0 ] ?? 0 ,
130+ y : row [ 1 ] ?? 0 ,
131+ z : row [ 2 ] ?? 0 ,
58132 } )
59133 ) ;
60134
61135 return (
62- < div className = "w-full h-full p-4 space-y-6 overflow-y-auto" >
63- < div className = "flex items-center gap-1" >
64- < h3 className = "text-2xl" > Kpoints Data</ h3 >
65- { /* for now we are downloading all the props. */ }
66- < DownloadIcon
67- data = { omitGraphKeys ( nodeData ) }
68- filename = { `${ nodeData . aiida . uuid } _KpointNodeDetails.json` }
69- size = { 22 }
70- className = "pb-0.5"
71- />
72- </ div >
136+ < div className = "w-full mx-auto p-4 space-y-2" >
137+ { /* Metadata / summary card */ }
138+
139+ { /* Brillouin Zone visualizer card */ }
140+ < CardContainer
141+ header = "Brillouin Zone"
142+ className = "!px-1.5 !py-2"
143+ childrenClassName = "!p-0"
144+ >
145+ < div className = "w-full" >
146+ < BZVisualizer
147+ data = { bzData }
148+ options = { {
149+ showAxes : true ,
150+ showBVectors : true ,
151+ showPathpoints : false ,
152+ disableInteractOverlay : true ,
153+ } }
154+ />
155+ </ div >
156+ </ CardContainer >
157+
158+ { /* Tables in cards */ }
159+ < DataTable
160+ title = "Recipricol cell vectors (1/Å)"
161+ columns = { recipColumns }
162+ data = { recipData }
163+ sortableCols = { false }
164+ />
165+
73166 < DataTable
74- key = "cell"
75167 title = "Cell"
76168 columns = { cellColumns }
77169 data = { cellData }
78170 sortableCols = { false }
79171 />
172+
80173 < DataTable
81- key = "mesh"
82174 title = "Mesh"
83175 columns = { meshColumns }
84176 data = { meshData }
85177 sortableCols = { false }
86178 />
179+
87180 < DataTable
88- key = "offset"
89181 title = "Offset"
90182 columns = { offsetColumns }
91183 data = { offsetData }
92184 sortableCols = { false }
93185 />
186+
94187 < DataTable
95- key = "pbc"
96188 title = "PBC Flags"
97189 columns = { pbcColumns }
98190 data = { pbcData }
99191 sortableCols = { false }
100192 />
193+
101194 < DataTable
102- key = "kpoints"
103195 title = "Explicit K-points (Absolute)"
104196 columns = { kpointColumns }
105197 data = { kpointData }
0 commit comments