@@ -72,28 +72,29 @@ const addSection = (
7272 data : InteractionData ,
7373 filterFn : ( type : string | null ) => boolean ,
7474 isLightMode : boolean ,
75- isFirstPage = false
75+ newPage : boolean = true ,
76+ startY : number = 20
7677) => {
7778 const margin = 15 ;
7879
79-
80- if ( ! isFirstPage ) {
80+ if ( newPage ) {
8181 doc . addPage ( ) ;
8282 }
8383
8484 // Title
8585 doc . setFont ( "helvetica" , "bold" ) ;
8686 doc . setFontSize ( 16 ) ;
87- doc . text ( title , margin , 20 ) ;
87+ doc . text ( title , margin , startY ) ;
8888
8989 // 1. Generate Image
9090 const mapImg = drawMapToDataURL ( data , filterFn , isLightMode ) ;
9191
9292 // 2. Add Image
9393 const desiredImgWidth = 100 ; // Fixed size
9494 const desiredImgHeight = 100 ;
95+ const imgY = startY + 10 ;
9596
96- doc . addImage ( mapImg , 'PNG' , margin , 30 , desiredImgWidth , desiredImgHeight ) ;
97+ doc . addImage ( mapImg , 'PNG' , margin , imgY , desiredImgWidth , desiredImgHeight ) ;
9798
9899 // 3. Generate Table Data
99100 const tableRows = [ ] as any [ ] ;
@@ -115,7 +116,7 @@ const addSection = (
115116 // Filter Row
116117 if ( filterFn ( type ) ) {
117118 // If generic "All" view, skip 'Close Contact' logs to save space for important stuff
118- if ( title === "All Interactions" && type === "Close Contact" ) continue ;
119+ if ( title . includes ( "All" ) && type === "Close Contact" ) continue ;
119120
120121 tableRows . push ( {
121122 res1 : `${ l1 . chain } :${ l1 . label } ` ,
@@ -134,10 +135,11 @@ const addSection = (
134135 const displayRows = tableRows . slice ( 0 , MAX_ROWS ) ;
135136
136137 doc . setFontSize ( 10 ) ;
137- doc . text ( `Identified Interactions (${ tableRows . length } total, top ${ displayRows . length } shown)` , margin , 30 + desiredImgHeight + 10 ) ;
138+ const summaryY = imgY + desiredImgHeight + 10 ;
139+ doc . text ( `Identified Interactions (${ tableRows . length } total, top ${ displayRows . length } shown)` , margin , summaryY ) ;
138140
139141 autoTable ( doc , {
140- startY : 30 + desiredImgHeight + 15 ,
142+ startY : summaryY + 5 ,
141143 head : [ [ 'Residue A' , 'Residue B' , 'Dist (Å)' , 'Type' ] ] ,
142144 body : displayRows . map ( r => [ r . res1 , r . res2 , r . dist , r . type ] ) ,
143145 theme : 'striped' ,
@@ -148,41 +150,37 @@ const addSection = (
148150
149151export const generateProteinReport = (
150152 proteinName : string ,
151- _canvasIgnored : HTMLCanvasElement , // We draw our own now
153+ _canvasIgnored : HTMLCanvasElement ,
152154 data : InteractionData
153155) => {
154156 const doc = new jsPDF ( ) ;
155- const isLightMode = true ; // Force light mode for print readability? Or pass user pref? Let's assume white paper = light mode.
157+ const isLightMode = false ; // Force DARK MODE for Maps (User Request)
156158
157159 // Page 1: Overview
158160 doc . setFont ( "helvetica" , "bold" ) ;
159161 doc . setFontSize ( 22 ) ;
160- doc . text ( "Protein Analysis Report" , 15 , 15 ) ;
162+ doc . text ( "Protein Analysis Report" , 15 , 20 ) ;
161163 doc . setFontSize ( 12 ) ;
162164 doc . setFont ( "helvetica" , "normal" ) ;
163- doc . text ( proteinName || "Unknown Protein" , 15 , 22 ) ;
165+ doc . text ( proteinName || "Unknown Protein" , 15 , 28 ) ;
164166
165- // Section 1: All Interactions (Salt Bridges, Disulfides, Pi, Hydrophobic)
166- // We allow everything except simple 'Close Contact' to declutter
167- const allFilter = ( t : string | null ) => t !== null && t !== 'Close Contact' ;
168- addSection ( doc , "All Significant Interactions" , data , allFilter , isLightMode , false ) ;
169- // Wait, first page logic is tricky with title.
170- // Let's make "All Interactions" start below the main title.
167+ doc . line ( 15 , 32 , 195 , 32 ) ;
171168
172- // Let's redefine addSection usage slightly or just manually do Page 1.
173- // Actually, let's just run addSection for everything and rely on auto-paging.
169+ // Section 1: All Interactions (Page 1, below header)
170+ const allFilter = ( t : string | null ) => t !== null && t !== 'Close Contact' ;
171+ addSection ( doc , "All Significant Interactions" , data , allFilter , isLightMode , false , 45 ) ;
174172
175- // 1 . Salt Bridge
176- addSection ( doc , "Salt Bridges (Ionic Interactions)" , data , ( t ) => t === 'Salt Bridge' , isLightMode , true ) ; // true = don't add page first (but we have title)
173+ // 2 . Salt Bridge
174+ addSection ( doc , "Salt Bridges (Ionic Interactions)" , data , ( t ) => t === 'Salt Bridge' , isLightMode , true ) ;
177175
178- // 2 . Disulfide
179- addSection ( doc , "Disulfide Bonds (Covalent)" , data , ( t ) => t === 'Disulfide Bond' , isLightMode , false ) ;
176+ // 3 . Disulfide
177+ addSection ( doc , "Disulfide Bonds (Covalent)" , data , ( t ) => t === 'Disulfide Bond' , isLightMode , true ) ;
180178
181- // 3 . Hydrophobic
182- addSection ( doc , "Hydrophobic Clusters" , data , ( t ) => t === 'Hydrophobic Contact' , isLightMode , false ) ;
179+ // 4 . Hydrophobic
180+ addSection ( doc , "Hydrophobic Clusters" , data , ( t ) => t === 'Hydrophobic Contact' , isLightMode , true ) ;
183181
184- // 4 . Pi-Stacking
185- addSection ( doc , "Pi-Stacking & Cation-Pi" , data , ( t ) => t === 'Pi-Stacking' || t === 'Cation-Pi Interaction' , isLightMode , false ) ;
182+ // 5 . Pi-Stacking
183+ addSection ( doc , "Pi-Stacking & Cation-Pi" , data , ( t ) => t === 'Pi-Stacking' || t === 'Cation-Pi Interaction' , isLightMode , true ) ;
186184
187185 // Save
188186 const safeName = proteinName . replace ( / [ ^ a - z 0 - 9 ] / yi, '_' ) . toLowerCase ( ) ;
0 commit comments