1
1
import React , { useContext , useEffect , useRef , useState } from "react" ;
2
- import AppContext , { ImageLoadInfo , AnalysisInfo } from "./components/interfaces" ;
2
+ import AppContext , { ImageLoadInfo , AnalysisInfo , IR_LIMIT_PX } from "./components/interfaces" ;
3
3
4
4
import Topbar from "./components/Topbar" ;
5
5
import DragDrop from "./components/DragDrop" ;
6
6
import PreviewCanvas from "./components/Canvas" ;
7
- import Menu from "./components/Modals" ;
7
+ import NormalSlider from "./components/NormalSlider" ;
8
+ import { Menu } from "./components/Menu" ;
9
+ import { ErrorMessage , CLSModal , MoreInfo } from "./components/Popups"
8
10
9
11
import { loadFromTIFF , loadFromImage } from "./components/imageLogic" ;
10
12
11
13
import "./assets/scss/App.scss" ;
12
14
import 'bootstrap/dist/css/bootstrap.min.css' ;
13
15
16
+ //const PATH = "http://127.0.0.1:5000";
17
+ const PATH = "https://samba-segment.azurewebsites.net" ;
18
+ //const PATH = "http://localhost:7071/api";
19
+ //const PATH = "https://representative.azurewebsites.net/api"
20
+ const PF_ENDPOINT = PATH + "/phasefraction"
21
+ //const PF_ENDPOINT = "https://representativity.azurewebsites.net/phasefraction"
22
+
23
+ //const REPR_ENDPOINT = PATH + "/repr";
24
+ const REPR_ENDPOINT = PATH + "/repr" ;
25
+
14
26
const MAX_FILE_SIZE_BYTES = 1024 * 1024 * 500 ; // 500MB
15
27
16
28
const App = ( ) => {
17
29
const {
18
30
imageInfo : [ imageInfo , setImageInfo ] ,
19
31
previewImg : [ previewImg , setPreviewImg ] ,
32
+ selectedPhase : [ selectedPhase , setSelectedPhase ] ,
33
+ selectedConf : [ selectedConf , setSelectedConf ] ,
34
+ errVF : [ errVF , setErrVF ] ,
20
35
targetL : [ targetL , setTargetL ] ,
36
+ pfB : [ , setPfB ] ,
37
+ accurateFractions : [ accurateFractions , setAccurateFractions ] ,
21
38
analysisInfo : [ , setAnalysisInfo ] ,
22
39
menuState : [ menuState , setMenuState ] ,
40
+ errorState : [ errorState , setErrorState ] ,
41
+ showWarning : [ showWarning , setShowWarning ] ,
23
42
} = useContext ( AppContext ) !
24
43
44
+
25
45
const appLoadFile = async ( file : File ) => {
26
46
const reader = new FileReader ( ) ;
27
47
const extension = file . name . split ( '.' ) . pop ( ) ?. toLowerCase ( ) ;
@@ -34,14 +54,14 @@ const App = () => {
34
54
} else if ( isPNGJPG ) {
35
55
reader . readAsDataURL ( file ) ;
36
56
} else {
37
- console . log ( `Unsupported file format .${ extension } ` ) ;
57
+ setErrorState ( { msg : `Unsupported file format .${ extension } ` , stackTrace : "" } )
38
58
return ;
39
59
} ;
40
60
41
61
reader . onload = async ( ) => {
42
62
let result : ImageLoadInfo | null = null ;
43
63
if ( file . size > MAX_FILE_SIZE_BYTES ) {
44
- console . log ( `File .${ file . size / ( 1000 * 1000 ) } MB greater than max size (500MB)` ) ;
64
+ setErrorState ( { msg : `File too large!` , stackTrace : `File .${ file . size / ( 1000 * 1000 ) } MB greater than max size (500MB)` } )
45
65
return ;
46
66
}
47
67
@@ -53,40 +73,125 @@ const App = () => {
53
73
} ;
54
74
console . log ( result ) ;
55
75
56
- if ( result ?. segmented == false ) {
57
- console . log ( 'error: unsegmented' ) ;
76
+ if ( result == null ) {
77
+ setErrorState ( {
78
+ msg : "Failed to load data" ,
79
+ stackTrace : ""
80
+ } ) ;
81
+ return ;
82
+ }
83
+
84
+ if ( result . segmented == false ) {
85
+ setErrorState ( {
86
+ msg : "Data is unsegmented - try using our web segmentation tool, SAMBA (https://www.sambasegment.com/)" ,
87
+ stackTrace : "Number of unique values > 6"
88
+ } ) ;
89
+ return ;
58
90
} else {
59
- result ! . file = file ;
91
+ if ( result . height < 200 || result . width < 200 || ( result . depth < 200 && result . depth > 1 ) ) {
92
+ setShowWarning ( "size" ) ;
93
+ }
94
+
95
+ requestPhaseFraction ( file ) ;
96
+ result . file = file ;
60
97
setImageInfo ( result ) ;
61
- setPreviewImg ( result ! . previewImg ) ;
98
+ setPreviewImg ( result . previewImg ) ;
62
99
setMenuState ( 'phase' ) ;
63
100
}
64
101
} ;
65
102
}
66
103
67
- useEffect ( ( ) => { // TODO: fetch from API instead
68
- if ( menuState === 'processing' ) {
69
- setMenuState ( 'conf_result' ) ;
70
- setTargetL ( 4 * imageInfo ?. width ! ) ;
104
+ const requestPhaseFraction = async ( file : File ) => {
105
+ try {
106
+ const formData = new FormData ( ) ;
107
+ formData . append ( 'userFile' , file ) ;
108
+ //formData.append('phaseVal', String(selectedPhaseValue));
109
+ const resp = await fetch ( PF_ENDPOINT , { method : 'POST' , body : formData } ) ;
110
+ const obj = await resp . json ( ) ;
111
+ const fractions = obj [ "phase_fractions" ] as { [ val : number ] : number } ;
112
+ setAccurateFractions ( fractions ) ;
113
+ } catch ( e ) {
114
+ const error = e as Error ;
115
+ setErrorState ( { msg : "Couldn't fetch phase fractions: data wrong or server down." , stackTrace : error . toString ( ) } ) ;
116
+ }
117
+ }
118
+
119
+ const requestRepr = async ( ) => {
120
+ try {
121
+ const info = imageInfo !
122
+
123
+ const formData = new FormData ( ) ;
124
+ formData . append ( 'userFile' , info . file ! ) ;
125
+ formData . append ( 'selected_phase' , String ( info . phaseVals [ selectedPhase - 1 ] ) ) ;
126
+ formData . append ( 'selected_conf' , String ( selectedConf ) ) ;
127
+ formData . append ( 'selected_err' , String ( errVF ) ) ;
128
+
129
+ const resp = await fetch ( REPR_ENDPOINT , { method : 'POST' , body : formData } ) ;
130
+ const obj = await resp . json ( ) ;
131
+
132
+ const absErr : number = obj [ "abs_err" ]
133
+
134
+ console . log ( obj )
135
+
136
+ setMenuState ( 'conf_result_full' ) ;
71
137
setAnalysisInfo ( {
72
- integralRange : 1 ,
138
+ integralRange : obj [ "cls" ] ,
73
139
z : 1 ,
74
- percentageErr : 5 ,
75
- absError : 5 * 0.45 ,
76
- lForDefaultErr : 4 * imageInfo ?. width ! ,
77
- vf : 0.45
140
+ stdModel : obj [ "std_model" ] ,
141
+ percentageErr : obj [ "percent_err" ] ,
142
+ absError : absErr ,
143
+ lForDefaultErr : obj [ "l" ] ,
144
+ vf : 1 ,
145
+ pf : obj [ 'pf_1d' ] ,
146
+ cumSumSum : obj [ "cum_sum_sum" ]
78
147
} )
148
+
149
+ const vals = imageInfo ?. phaseVals !
150
+ const phaseFrac = accurateFractions ! [ vals [ selectedPhase - 1 ] ]
151
+ setPfB ( [ phaseFrac - absErr , phaseFrac + absErr ] )
152
+
153
+ if ( obj [ "cls" ] > IR_LIMIT_PX ) { setShowWarning ( "cls" ) }
154
+ const minSide = Math . min ( imageInfo ?. width ! , imageInfo ?. height ! )
155
+ if ( obj [ "l" ] < minSide ) { setShowWarning ( "over" ) }
156
+
157
+ setTargetL ( obj [ "l" ] ) ;
158
+ } catch ( e ) {
159
+ const error = e as Error ;
160
+ setErrorState ( { msg : "Couldn't determine representativity: data wrong or server down." , stackTrace : error . toString ( ) } ) ;
161
+ }
162
+ }
163
+
164
+ const reset = ( ) => {
165
+ setMenuState ( 'hidden' ) ;
166
+ setPreviewImg ( null ) ;
167
+ setImageInfo ( null ) ;
168
+ setAnalysisInfo ( null ) ;
169
+ setTargetL ( null ) ;
170
+ setAccurateFractions ( null ) ;
171
+ setPreviewImg ( null ) ;
172
+ setSelectedPhase ( 0 ) ;
173
+ setErrVF ( 5 ) ;
174
+ setSelectedConf ( 95 ) ;
175
+ }
176
+
177
+ useEffect ( ( ) => { // TODO: fetch from API instead
178
+ if ( menuState === 'processing' ) {
179
+ requestRepr ( ) ;
79
180
}
80
181
} , [ menuState ] )
81
182
82
183
return (
83
184
< div className = { `w-full h-full` } >
84
- < Topbar > </ Topbar >
185
+ < Topbar loadFromFile = { appLoadFile } reset = { reset } > </ Topbar >
85
186
< div className = { `flex` } style = { { margin : '1.5%' } } > { /*Canvas div on left, sidebar on right*/ }
86
187
{ ! previewImg && < DragDrop loadFromFile = { appLoadFile } /> }
87
188
{ previewImg && < PreviewCanvas /> }
189
+ { false && < NormalSlider /> }
88
190
</ div >
89
- < Menu > </ Menu >
191
+ < Menu />
192
+ < ErrorMessage />
193
+ { showWarning != "" && < CLSModal /> }
194
+ < MoreInfo />
90
195
</ div >
91
196
) ;
92
197
} ;
0 commit comments