summaryrefslogtreecommitdiff
path: root/app/client/modules/pix2pix/views
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2018-06-05 22:02:19 +0200
committerJules Laplace <julescarbon@gmail.com>2018-06-05 22:02:19 +0200
commit5c018b3f2c2c47371546d210240836057d1ea5bb (patch)
tree3e802344413007612b7073548756d32aa77074f4 /app/client/modules/pix2pix/views
parent2b4a6e53102b568c691c72998ddece80a3b3d515 (diff)
set menu dropdown from url. make pix2pix views
Diffstat (limited to 'app/client/modules/pix2pix/views')
-rw-r--r--app/client/modules/pix2pix/views/pix2pix.live.js253
-rw-r--r--app/client/modules/pix2pix/views/pix2pix.new.js16
-rw-r--r--app/client/modules/pix2pix/views/pix2pix.show.js115
3 files changed, 384 insertions, 0 deletions
diff --git a/app/client/modules/pix2pix/views/pix2pix.live.js b/app/client/modules/pix2pix/views/pix2pix.live.js
new file mode 100644
index 0000000..fc6bc9b
--- /dev/null
+++ b/app/client/modules/pix2pix/views/pix2pix.live.js
@@ -0,0 +1,253 @@
+import { h, Component } from 'preact'
+import { bindActionCreators } from 'redux'
+import { connect } from 'react-redux'
+
+import Player from '../../../common/player.component'
+import ParamGroup from '../../../common/paramGroup.component'
+import Slider from '../../../common/slider.component'
+import Select from '../../../common/select.component'
+import Button from '../../../common/button.component'
+
+import { startRecording, stopRecording, saveFrame } from '../../../live/player'
+
+import * as liveActions from '../../../live/live.actions'
+
+class Pix2PixLive extends Component {
+ constructor(props){
+ super()
+ props.actions.get_params()
+ props.actions.list_checkpoints()
+ props.actions.list_sequences()
+ this.changeCheckpoint = this.changeCheckpoint.bind(this)
+ this.changeEpoch = this.changeEpoch.bind(this)
+ this.changeSequence = this.changeSequence.bind(this)
+ this.seek = this.seek.bind(this)
+ this.togglePlaying = this.togglePlaying.bind(this)
+ this.toggleRecording = this.toggleRecording.bind(this)
+ }
+ componentWillUpdate(nextProps) {
+ if (nextProps.opt.checkpoint_name && nextProps.opt.checkpoint_name !== this.props.opt.checkpoint_name) {
+ this.props.actions.list_epochs(nextProps.opt.checkpoint_name)
+ }
+ }
+ changeCheckpoint(checkpoint_name){
+ this.props.actions.load_epoch(checkpoint_name, 'latest')
+ }
+ changeEpoch(epoch_name){
+ this.props.actions.load_epoch(this.props.opt.checkpoint_name, epoch_name)
+ }
+ changeSequence(sequence){
+ console.log('got sequence', sequence)
+ this.props.actions.load_sequence(sequence)
+ }
+ seek(percentage){
+ const frame = Math.floor(percentage * (parseInt(this.props.frame.sequence_len) || 1) + 1)
+ this.props.actions.seek(frame)
+ }
+ togglePlaying(){
+ if (this.props.opt.processing) {
+ this.props.actions.pause()
+ } else {
+ this.props.actions.play()
+ }
+ }
+ toggleRecording(){
+ if (this.props.opt.recording){
+ stopRecording()
+ this.props.actions.pause()
+ } else {
+ startRecording()
+ }
+ }
+ render(){
+ return (
+ <div className='app centered'>
+ <Player width={424} height={256} />
+ <div className='params row'>
+ <div className='column'>
+ <ParamGroup
+ title='Playback'
+ noToggle
+ >
+ <Select
+ name='send_image'
+ title='view mode'
+ options={['a','b','sequence','recursive']}
+ onChange={this.props.actions.set_param}
+ />
+ <Select
+ name='sequence_name'
+ title='sequence'
+ options={this.props.sequences}
+ onChange={this.changeSequence}
+ />
+ <Select
+ name='checkpoint_name'
+ title='checkpoint'
+ options={this.props.checkpoints}
+ onChange={this.changeCheckpoint}
+ />
+ <Select
+ name='epoch'
+ title='epoch'
+ options={this.props.epochs}
+ onChange={this.changeEpoch}
+ />
+ <Slider
+ name='position'
+ min={0.0} max={1.0} type='float'
+ value={(this.props.frame.sequence_i || 0) / (this.props.frame.sequence_len || 1)}
+ onChange={this.seek}
+ />
+ <Button
+ title={'Processing: ' + (this.props.opt.processing ? 'yes' : 'no')}
+ onClick={this.togglePlaying}
+ >
+ {this.props.opt.processing ? 'Pause' : 'Restart'}
+ </Button>
+ <Button
+ title={
+ this.props.opt.savingVideo
+ ? 'Saving video...'
+ : this.props.opt.recording
+ ? 'Recording (' + timeInSeconds(this.props.opt.recordFrames) +')'
+ : 'Record video'
+ }
+ onClick={this.toggleRecording}
+ >
+ {this.props.opt.savingVideo ? 'Saving' : this.props.opt.recording ? 'Recording' : 'Record'}
+ </Button>
+ <Button
+ title={'Save frame'}
+ onClick={saveFrame}
+ >
+ Save
+ </Button>
+ </ParamGroup>
+ </div>
+ <div className='column'>
+ <ParamGroup
+ title='Transition'
+ name='transition'
+ >
+ <Slider
+ name='transition_period'
+ min={10} max={5000} type='int'
+ />
+ <Slider
+ name='transition_min'
+ min={0.001} max={0.2} type='float'
+ />
+ <Slider
+ name='transition_max'
+ min={0.1} max={1.0} type='float'
+ />
+ </ParamGroup>
+
+ <ParamGroup
+ title='Recursion'
+ name='recursive'
+ >
+ <Slider
+ name='recursive_frac'
+ min={0.0} max={0.5} type='float'
+ />
+ <Slider
+ name='recurse_roll'
+ min={-64} max={64} type='int'
+ />
+ <Slider
+ name='recurse_roll_axis'
+ min={0} max={1} type='int'
+ />
+ </ParamGroup>
+
+ <ParamGroup
+ title='Sequence'
+ name='sequence'
+ >
+ <Slider
+ name='sequence_frac'
+ min={0.0} max={0.5} type='float'
+ />
+ <Slider
+ name='process_frac'
+ min={0} max={1} type='float'
+ />
+ </ParamGroup>
+ </div>
+ <div className='column'>
+ <ParamGroup
+ title='Clahe'
+ name='clahe'
+ >
+ <Slider
+ name='clip_limit'
+ min={1.0} max={4.0} type='float'
+ />
+ </ParamGroup>
+
+ <ParamGroup
+ title='Posterize'
+ name='posterize'
+ >
+ <Slider
+ name='spatial_window'
+ min={2} max={128} type='int'
+ />
+ <Slider
+ name='color_window'
+ min={2} max={128} type='int'
+ />
+ </ParamGroup>
+
+ <ParamGroup
+ title='Blur'
+ name='blur'
+ >
+ <Slider
+ name='blur_radius'
+ min={3} max={7} type='odd'
+ />
+ <Slider
+ name='blur_sigma'
+ min={0} max={2} type='float'
+ />
+ </ParamGroup>
+
+ <ParamGroup
+ title='Canny Edge Detection'
+ name='canny'
+ >
+ <Slider
+ name='canny_lo'
+ min={10} max={200} type='int'
+ />
+ <Slider
+ name='canny_hi'
+ min={10} max={200} type='int'
+ />
+ </ParamGroup>
+
+ </div>
+ </div>
+ </div>
+ )
+ }
+}
+function timeInSeconds(n){
+ return (n / 10).toFixed(1) + ' s.'
+}
+const mapStateToProps = state => ({
+ opt: state.live.opt,
+ frame: state.live.frame,
+ checkpoints: state.live.checkpoints,
+ epochs: state.live.epochs,
+ sequences: state.live.sequences,
+})
+
+const mapDispatchToProps = (dispatch, ownProps) => ({
+ actions: bindActionCreators(liveActions, dispatch)
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(Pix2PixLive)
diff --git a/app/client/modules/pix2pix/views/pix2pix.new.js b/app/client/modules/pix2pix/views/pix2pix.new.js
new file mode 100644
index 0000000..173777c
--- /dev/null
+++ b/app/client/modules/pix2pix/views/pix2pix.new.js
@@ -0,0 +1,16 @@
+import { h, Component } from 'preact'
+import { bindActionCreators } from 'redux'
+import { connect } from 'react-redux'
+import * as util from '../../../util'
+
+import NewDatasetForm from '../../../dataset/dataset.new'
+
+import pix2pixModule from '../pix2pix.module'
+
+export default function Pix2PixNew ({ history }) {
+ return (
+ <div class='app pix2pix'>
+ <NewDatasetForm module={pix2pixModule} history={history} />
+ </div>
+ )
+}
diff --git a/app/client/modules/pix2pix/views/pix2pix.show.js b/app/client/modules/pix2pix/views/pix2pix.show.js
new file mode 100644
index 0000000..b4cdc50
--- /dev/null
+++ b/app/client/modules/pix2pix/views/pix2pix.show.js
@@ -0,0 +1,115 @@
+import { h, Component } from 'preact'
+import { bindActionCreators } from 'redux'
+import { connect } from 'react-redux'
+import * as util from '../../../util'
+
+import * as pix2pixActions from '../pix2pix.actions'
+import * as pix2pixTasks from '../pix2pix.tasks'
+
+import Loading from '../../../common/loading.component'
+import DatasetForm from '../../../dataset/dataset.form'
+import NewDatasetForm from '../../../dataset/dataset.new'
+import UploadStatus from '../../../dataset/upload.status'
+import { FileList, FileRow } from '../../../common/fileList.component'
+
+import DatasetComponent from '../../../dataset/dataset.component'
+
+import pix2pixModule from '../pix2pix.module'
+
+class Pix2pixShow extends Component {
+ constructor(props){
+ super(props)
+ this.datasetActions = this.datasetActions.bind(this)
+ }
+ componentWillMount(){
+ const id = this.props.match.params.id || localStorage.getItem('pix2pix.last_id')
+ console.log('load dataset:', id)
+ const { match, pix2pix, actions } = this.props
+ if (id === 'new') return
+ if (id) {
+ if (parseInt(id)) localStorage.setItem('pix2pix.last_id', id)
+ if (! pix2pix.folder || pix2pix.folder.id !== id) {
+ actions.load_directories(id)
+ }
+ }
+ }
+ render(){
+ const { pix2pix, match, history } = this.props
+ const { folderLookup } = (pix2pix.data || {})
+ const folder = (folderLookup || {})[pix2pix.folder_id] || {}
+ return (
+ <div className='app pix2pix'>
+ <div class='heading'>
+ <div class='spaced'>
+ <h1>{folder ? folder.name : <Loading />}</h1>
+ <UploadStatus />
+ </div>
+ </div>
+ {folder && folder.name && folder.name !== 'unsorted' &&
+ <DatasetForm
+ title='Add Files'
+ module={pix2pixModule}
+ folder={folder}
+ canUpload canAddURL
+ />
+ }
+ <DatasetComponent
+ loading={pix2pix.loading}
+ progress={pix2pix.progress}
+ id={pix2pix.folder_id}
+ module={pix2pixModule}
+ data={pix2pix.data}
+ folder={folder}
+ history={history}
+ onPickFile={(file, e) => {
+ e.preventDefault()
+ e.stopPropagation()
+ console.log('picked a file', file)
+ }}
+ datasetActions={this.datasetActions}
+ />
+ </div>
+ )
+ }
+ datasetActions(dataset, isFetching=false, isProcessing=false){
+ const { pix2pix, remote } = this.props
+ const input = pix2pix.data.fileLookup[dataset.input[0]]
+ if (! input) return null
+ if (input.name && input.name.match(/(gif|jpe?g|png)$/i)) return null
+ return (
+ <div>
+ <div class={'actions'}>
+ <span class='link' onClick={() => remote.train_task(dataset, pix2pix.folder_id, 1)}>train</span>
+ <span class='link' onClick={() => remote.train_task(dataset, pix2pix.folder_id, 2)}>2x</span>
+ <span class='link' onClick={() => remote.train_task(dataset, pix2pix.folder_id, 4)}>4x</span>
+ <span class='link' onClick={() => remote.train_task(dataset, pix2pix.folder_id, 6)}>6x</span>
+ <span class='link' onClick={() => remote.train_task(dataset, pix2pix.folder_id, 18)}>18x</span>
+ </div>
+ {dataset.isBuilt
+ ? <div class='subtext'>
+ {'fetched '}
+ <span class='link' onClick={() => remote.clear_cache_task(dataset)}>rm</span>
+ </div>
+ : isFetching
+ ? <div class='subtext'>
+ {'fetching'}
+ </div>
+ : <div class='subtext'>
+ <span class='link' onClick={() => remote.fetch_task(input.url, input.id, dataset.name)}>fetch</span>
+ </div>
+ }
+ </div>
+ )
+ }
+}
+
+const mapStateToProps = state => ({
+ pix2pix: state.module.pix2pix,
+})
+
+const mapDispatchToProps = (dispatch, ownProps) => ({
+ actions: bindActionCreators(pix2pixActions, dispatch),
+ remote: bindActionCreators(pix2pixTasks, dispatch),
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(Pix2pixShow)