691 lines (553 with data), 18.4 kB
#:kivy 1.10.0
#:import color src.color
#:import util src.util
<Widget>:
font_name: 'Roboto-Bold'
font_size: 16
<Spacer@Widget>:
size_hint: 1, 1
<HSpacer@Widget>:
size_hint: 1, None
<VSpacer@Widget>:
size_hint: None, 1
<HDivider@Widget>:
size_hint: 1, None
height: 3
canvas.before:
Color:
rgba: 0, 0, 0, .08
Rectangle:
pos: self.pos
size: self.size
<LeftLabel@Label>:
font_name: 'Roboto'
size_hint: None, None
color: .4, .4, .4, 1
halign: 'left'
on_texture_size:
self.width = 40 + self.texture.width
self.height = self.texture.height
<TextButton@Button>:
background_normal: ''
background_color: 0, 0, 0, 0
size_hint: None, None
bold: True
color: color.B4 if self.state == 'normal' else color.B3
halign: 'left'
canvas.before:
Color:
rgba: (0, 0, 0, .01) if self.state != 'normal' else (0, 0, 0, 0)
RoundedRectangle:
size: self.size
pos: self.pos
on_texture_size:
self.width = 40 + self.texture.width
self.height = self.texture.height
<Card@BoxLayout>:
size_hint: None, None
orientation: 'vertical'
background_color: 0, 0, 0, 0
bg_color: 1, 1, 1, 1
radius: 20
canvas.before:
Rectangle:
size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
pos: self.pos[0] - self.radius, self.pos[1] - 1.5 * self.radius
texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, 0.8 * self.radius, 0.4)
Color:
rgba: self.bg_color
Rectangle:
size: self.size
pos: self.pos
<Chip>:
size_hint: None, None
height: self.minimum_height
width: self.minimum_width
radius: 5
selected: True
text: ''
canvas.before:
Rectangle:
size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
pos: self.pos[0] - self.radius, self.pos[1] - 1.5 * self.radius
texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, self.radius, 0.3)
Color:
rgb: (.85, .85, .85) if self.selected else (.95, .95, .95)
RoundedRectangle:
size: self.size
pos: self.pos
radius: [4]
<ChipInput>:
padding: [10, 0, 5, 0]
spacing: 0
hint_text: ''
TextInput:
id: input
background: ''
background_color: 0, 0, 0, 0
multiline: False
font_name: 'Roboto'
size_hint: None, None
size: 80, self.minimum_height - 2
hint_text: self.hint_text
on_text_validate:
root.submit()
on_text:
self.width = max(80, 20 + self._lines_labels[0].size[0] if self._lines_labels else 0)
canvas.before:
Color:
rgb: .4, .4, .4
<ChipInputAdder>:
padding: [10, 0, 5, 0]
spacing: 0
hint_text: ''
TextInput:
id: input
background: ''
background_color: 0, 0, 0, 0
multiline: False
font_name: 'Roboto'
size_hint: None, None
size: 80, self.minimum_height - 2
hint_text: self.hint_text
on_text_validate:
root.submit()
on_text:
self.width = max(80, 20 + self._lines_labels[0].size[0] if self._lines_labels else 0)
canvas.before:
Color:
rgb: .4, .4, .4
Button:
size_hint: None, 1
width: self.height
background_normal: ''
background_color: 0, 0, 0, 0
canvas.before:
Color:
rgba: (.6, .6, .6, 1) if self.state == 'normal' else (.5, .5, .5, 1)
Line:
points: [self.pos[0] + self.height * .3, self.pos[1] + self.height * .5, self.pos[0] + self.height * .7, self.pos[1] + self.height * .5]
width: self.height / 20
cap: 'square'
Line:
points: [self.pos[0] + self.height * .5, self.pos[1] + self.height * .3, self.pos[0] + self.height * .5, self.pos[1] + self.height * .7]
width: self.height / 20
cap: 'square'
on_press:
root.submit()
<ChipRemovable>:
selected: False
padding: [10, 5, 5, 5]
spacing: 10
Label:
font_name: 'Roboto'
size_hint: None, None
color: .4, .4, .4, 1
halign: 'left'
text: root.text
on_texture_size:
self.size = self.texture.size
Button:
id: btn_remove
size_hint: None, 1
width: self.height
background_normal: ''
background_color: 0, 0, 0, 0
canvas.before:
Color:
rgba: (.6, .6, .6, 1) if self.state == 'normal' else (.5, .5, .5, 1)
Line:
points: [self.pos[0] + self.height * .3, self.pos[1] + self.height * .3, self.pos[0] + self.height * .7, self.pos[1] + self.height * .7]
width: self.height / 20
Line:
points: [self.pos[0] + self.height * .3, self.pos[1] + self.height * .7, self.pos[0] + self.height * .7, self.pos[1] + self.height * .3]
width: self.height / 20
on_press:
root.remove()
<Body@Card>:
orientation: 'vertical'
size_hint: 1, None
pos_hint: { 'center_x': .5, 'center_y': .5 }
padding: 20
spacing: 20
<HPage@ScrollView>:
do_scroll_x: False
do_scroll_y: True
<HPageBox@BoxLayout>:
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
padding: 20
<HPageBody@Body>:
height: self.minimum_height
<HTitle@Label>:
size_hint: 1, None
height: 40
color: .4, .4, .4, 1
font_name: 'RobotoMono-Regular'
<HStack@StackLayout>:
size_hint: 1, None
height: self.minimum_height
spacing: 10
<PopupFileLoader>:
size_hint: None, None
size: 500, 500
title: ''
title_color: .4, .4, .4, 1
background: ''
background_color: 0, 0, 0, 0
separator_height: 0
radius: 10
file_path: None
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
pos: self.pos[0] - self.radius, self.pos[1] - 2 * self.radius
texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, self.radius, 0.4)
BoxLayout:
orientation: 'vertical'
FileChooserListView:
id: file_chooser
color: 0, 0, 0, 1
dirselect: True
path: util.samples_dir
on_selection:
root.selectFile(args[1])
on_submit:
root.submitFile()
BoxLayout:
size_hint: 1, None
height: self.minimum_height + 10
TextButton:
text: 'SELECT'
on_press:
root.submitFile()
TextButton:
text: 'CLOSE'
on_press:
root.dismiss()
<FileChooserListView>:
layout: layout
FileChooserListLayout:
id: layout
controller: root
[FileListEntry@FloatLayout+TreeViewNode]:
locked: False
entries: []
path: ctx.path
is_selected: self.path in ctx.controller().selection
orientation: 'horizontal'
size_hint_y: None
height: '48dp' if dp(1) > 1 else '24dp'
is_leaf: not ctx.isdir or ctx.name.endswith('..' + ctx.sep) or self.locked
on_touch_down: self.collide_point(*args[1].pos) and ctx.controller().entry_touched(self, args[1])
on_touch_up: self.collide_point(*args[1].pos) and ctx.controller().entry_released(self, args[1])
BoxLayout:
pos: root.pos
size_hint_x: None
width: root.width - dp(10)
Label:
color: .4, .4, .4, 1
id: filename
text_size: self.width, None
halign: 'left'
shorten: True
text: ctx.name
Label:
color: .4, .4, .4, 1
text_size: self.width, None
size_hint_x: None
halign: 'right'
text: '{}'.format(ctx.get_nice_size())
<ScreenCard@Card>:
width: min(600, self.parent.width - 40)
padding: 20
spacing: 8
<StartScreenLabel@Label>:
size_hint: None, None
bold: True
color: .4, .4, .4, 1
halign: 'left'
on_texture_size:
self.width = 40 + (self.texture.width if self.text else 0)
self.height = self.texture.height
<SpaceStart>:
HPage:
HPageBox:
HPageBody:
pos_hint: { 'center_x': .5, 'center_y': .5 }
size_hint: None, None
width: min(900, 0.8 * root.width)
height: max(0.9 * root.height, self.minimum_height)
HTitle:
font_size: 40
text: 'APOS'
HTitle:
font_name: 'Roboto'
color: color.B3
font_size: 20
bold: True
text: 'Advanced Pathology OS'
ScreenCard:
height: 130
StartScreenLabel:
text: 'START'
HSpacer:
height: 3
TextButton:
text: 'Create slide'
on_press:
app.root.ids.workspace.transition.direction = 'left'
app.root.ids.workspace.current = 'screen_createslide'
TextButton:
text: 'Analyze slide'
on_press:
app.root.ids.workspace.transition.direction = 'left'
app.root.ids.workspace.current = 'screen_analyze'
Spacer:
ScreenCard:
height: 130
StartScreenLabel:
text: 'TRAIN'
HSpacer:
height: 3
TextButton:
text: 'Create disease filter'
on_press:
app.root.ids.workspace.transition.direction = 'right'
app.root.ids.workspace.current = 'screen_train'
TextButton:
text: 'Categorize training data'
on_press:
app.root.ids.workspace.transition.direction = 'right'
app.root.ids.workspace.current = 'screen_categorize'
Spacer:
ScreenCard:
height: 100
StartScreenLabel:
text: 'MISCELLANEOUS'
HSpacer:
height: 3
TextButton:
text: 'System Info'
on_press:
app.root.ids.workspace.transition.direction = 'up'
app.root.ids.workspace.current = 'screen_credits'
Spacer:
Spacer:
LeftLabel:
font_size: 13
font_name: 'RobotoMono-Regular'
text: util.app_creators
<ReturnToMain@TextButton>:
text: 'BACK'
dir: 'right'
on_press:
app.root.ids.workspace.transition.direction = self.dir
app.root.ids.workspace.current = 'screen_start'
<SpaceCreateSlide>:
HPage:
HPageBox:
HPageBody:
TextButton:
text: 'BACK'
on_press:
app.root.ids.workspace.current = 'screen_start'
app.root.ids.workspace.transition.direction = 'right'
HTitle:
text: 'Create Slide'
HDivider:
ImagePlot:
size: 600, 600
id: plot
HDivider:
HStack:
LeftLabel:
text: 'IP address'
ChipInput:
hint_text: 'Ip Address'
callback: root.set_ip
HStack:
TextButton:
id: btn_start
text: 'Start Webcam'
on_press:
root.toggle_webcam()
TextButton:
text: 'Capture Image'
on_press:
root.capture()
<FilterApply>:
size_hint: None, None
size: 400, 80
radius: 8
padding: 5
text: ''
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
pos: self.pos[0] - self.radius, self.pos[1] - 1.5 * self.radius
texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, 0.8 * self.radius, 0.3)
Color:
rgba: 1, 1, 1, 1
Rectangle:
size: self.size
pos: self.pos
LeftLabel:
font_name: 'RobotoMono-Regular'
color: .4, .4, .4, 1
text: root.text
HSpacer:
height: 10
HStack:
TextButton:
id: btn_train
text: 'Analyze'
on_press:
root.analysis_callback()
TextButton:
id: btn_reset
text: 'Reset'
on_press:
root.reset()
<SpaceAnalyze>:
HPage:
HPageBox:
HPageBody:
TextButton:
text: 'BACK'
on_press:
app.root.ids.workspace.transition.direction = 'right'
app.root.ids.workspace.current = 'screen_start'
HTitle:
text: 'Analyze Slide'
HDivider:
HStack:
ImageLoader:
size: 450, 450
id: slide
ImagePlot:
size: 450, 450
id: sub_sample
TextButton:
text: 'Select Slide'
on_press:
root.ids.slide.popup_selectImage()
HDivider:
LeftLabel:
font_name: 'RobotoMono-Regular'
text: 'REPORT'
bold: True
LeftLabel:
font_name: 'RobotoMono-Regular'
id: info
text: ''
HDivider:
TextButton:
text: 'Reload Filters'
on_press:
root.loadFilters()
HStack:
id: filter_list
<FilterTrain>:
size_hint: None, None
size: 600, 400
radius: 8
padding: 5
text: ''
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
size: self.size[0] + 2 * self.radius, self.size[1] + 2 * self.radius
pos: self.pos[0] - self.radius, self.pos[1] - 1.5 * self.radius
texture: color.createBoxShadow(self.size[0] + self.radius, self.size[1] + self.radius, 0.8 * self.radius, 0.3)
Color:
rgba: 1, 1, 1, 1
Rectangle:
size: self.size
pos: self.pos
LeftLabel:
font_name: 'RobotoMono-Regular'
color: .4, .4, .4, 1
text: root.text
HSpacer:
height: 10
HStack:
TextButton:
id: btn_train
text: 'Train'
on_press:
root.train()
root.ids.btn_save.text = 'Save'
TextButton:
id: btn_save
text: ''
on_press:
text: 'Saving ...'
root.save()
<SpaceTrain>:
HPage:
HPageBox:
HPageBody:
ReturnToMain:
dir: 'left'
HTitle:
text: 'Create Filter'
HDivider:
HStack:
ImagePlot:
id: plot
HStack:
TextButton:
text: 'Load Filters'
on_press:
root.load_filters()
HDivider:
HStack:
id: filter_editor
<SpaceFixedBody@Body>:
size_hint: .9, .8
size_hint_max: 1000, 800
size_hint_min: 500, 500
<SpaceCategorize>:
slide_img: None
HPage:
HPageBox:
HPageBody:
TextButton:
text: 'BACK'
dir: 'right'
on_press:
app.root.ids.workspace.transition.direction = self.dir
app.root.ids.workspace.current = 'screen_start'
HTitle:
text: 'Categorize'
StackLayout:
size_hint: 1, None
width: self.minimum_width
height: self.minimum_height
spacing: 10
ImageLoader:
size: 350, 350
id: slide
ImageLoader:
size: 350, 350
id: sub_sample
<SpaceCredits>:
SpaceFixedBody:
ReturnToMain:
dir: 'down'
Label:
color: .4, .4, .4, 1
text: util.app_credits
font_name: 'RobotoMono-Regular'
size_hint: 1, .5
<MainWindow>:
title: 'MicroLab - DeepStain'
WorkSpace:
id: workspace