<commit_before>var async = require('async'),
  hat = require('hat'),
  rack = hat.rack(),
  LocalStrategy = require('passport-local').Strategy,
  HashStrategy = require('passport-hash').Strategy,
  GoogleStrategy = require('passport-google').Strategy,
  GitHubStrategy = require('passport-github').Strategy,
  TwitterStrategy = require('passport-twitter').Strategy,
  FacebookStrategy = require('passport-facebook').Strategy;

exports.doInitializePassportStrategies = function (passport, Users, config) {
  //initializing passport strategies
  passport.use(new LocalStrategy(
    function (username, password, done) {
      Users.findOne({username: username, active: true}, function (err, user) {
        if (err) {
          return done(err, false, {'message': 'Database broken...'});
        } else {
          if (user) {
            if (user.verifyPassword(password)) {
              return done(null, user, {message: 'Welcome, ' + user.username});
            } else {
              return done(null, false, { message: 'Access denied!' });
            }
          } else {
            return done(null, false, { message: 'Access denied!' });
          }
        }
      });
    }
  ));

  //used for verify account by email
  passport.use(new HashStrategy(function(hash,done){
    //todo - need to refactor user class for it...
  }));

  passport.use(new GoogleStrategy({
      returnURL: config.hostUrl + 'auth/google/return',
      realm: config.hostUrl
    },
    function (identifier, profile, done) {
      var email = profile.emails[0].value;
      console.log(profile);
      Users.findOne({'email': email, active: true}, function (err, userFound) {
        console.log(userFound);
        if (userFound) {
          done(err, userFound, {message: 'Welcome, ' + userFound.username});
        } else {
          //model.UserModel.create({email:email},function(err,userCreated){
          done(err, false, { message: 'Access denied!' });//todo - i am not sure if user can register by singing in with Google Acount
          //});
        }
      });
    }
  ));

  if (config.passport && config.passport.GITHUB_CLIENT_ID && config.passport.GITHUB_CLIENT_SECRET) {
    //if we have set parameters for github, enable the github passport strategy
    passport.use(new GitHubStrategy({
      clientID: config.passport.GITHUB_CLIENT_ID,
      clientSecret: config.passport.GITHUB_CLIENT_SECRET,
      callbackURL: config.hostUrl + 'auth/github/callback'
    }, function (accessToken, refreshToken, profile, done) {
      var email = profile.emails[0].value;
      console.log(profile);
      Users.findOne({'email': email, active: true}, function (err, userFound) {
        console.log(userFound);
        if (userFound) {
          done(err, userFound, {message: 'Welcome, ' + userFound.username});
        } else {
          //model.UserModel.create({email:email},function(err,userCreated){
          done(err, false, { message: 'Access denied!' });//todo - i am not sure if user can register by singing in with Github Account
          //});
        }
      });
    }));
  }

  if (config.passport && config.passport.TWITTER_CONSUMER_KEY && config.passport.TWITTER_CONSUMER_SECRET) {
    passport.use(new TwitterStrategy({
      consumerKey: config.passport.TWITTER_CONSUMER_KEY,
      consumerSecret: config.passport.TWITTER_CONSUMER_SECRET,
      callbackURL: config.hostUrl + 'auth/twitter/callback'
    }, function (token, tokenSecret, profile, done) {
      var email = profile.emails[0].value;
      console.log(profile);
      Users.findOne({'email': email, active: true}, function (err, userFound) {
        console.log(userFound);
        if (userFound) {
          done(err, userFound, {message: 'Welcome, ' + userFound.username});
        } else {
          //model.UserModel.create({email:email},function(err,userCreated){
          done(err, false, { message: 'Access denied!' });//todo - i am not sure if user can register by singing in with Twitter Account
          //});
        }
      });
    }));
  }

  if (config.passport && config.passport.FACEBOOK_APP_ID && config.passport.FACEBOOK_APP_SECRET) {
    passport.use(new FacebookStrategy({
        clientID: config.passport.FACEBOOK_APP_ID,
        clientSecret: config.passport.FACEBOOK_APP_SECRET,
        callbackURL: config.hostUrl + 'auth/facebook/callback'
      },
      function(accessToken, refreshToken, profile, done) {
        var email = profile.emails[0].value;
        console.log(profile);
        Users.findOne({'email': email, active: true}, function (err, userFound) {
          console.log(userFound);
          if (userFound) {
            done(err, userFound, {message: 'Welcome, ' + userFound.username});
          } else {
            //model.UserModel.create({email:email},function(err,userCreated){
            done(err, false, { message: 'Access denied!' });//todo - i am not sure if user can register by singing in with Facebook Account
            //});
          }
        });
      }));
  }

  //end of initializing passport strategies

  //Storing user in session, storage key is username
  passport.serializeUser(function (user, done) {
    done(null, user.username);
  });

  passport.deserializeUser(function (username, done) {
    Users.findOne({username: username}, function (err, user) {
      done(err, user);
    });
  });
  //end of setting passport

}
exports.doInitializePassportRoutes = function (passport, app, config) {

  //registration by username, password and email
  //todo - implement the https://npmjs.org/packages/captcha
  app.post('/auth/signup',function(request,response){
    async.waterfall(
      [
        function (cb) {
          request.MODEL.Users.create({
            'username': request.body.username,
            'email': request.body.email,
            'apiKey': rack(),
            'confirmation':{
              'string':rack(),
              'date': new Date()
            }
          }, function (err, userCreated) {
            cb(err, userCreated);
          });
        },
        function (userCreatedReadyForSettingPassword, cb) {
          userCreatedReadyForSettingPassword.setPassword(request.params.password, function (err) {
            cb(err,userCreatedReadyForSettingPassword);
          });
        },
        function (userToNeNotified,cb){
          //to be implemented
          //userToNeNotified.notify()
          cb(null, true)
        }
      ], function (err, result) {
        if(err) throw err;
        if(result){
          request.flash('info','You have been registered! Please, check your email for instructions!');
          response.redirect('/');
        }
      });
  });

  //verify that login/email is not busy! - to be called by ajax
  app.get('/auth/isBusy',function(request,response){
    async.parallel({
      'username_ok':function(cb){
        var username=request.query.username;
        if(username){
          if(/^[a-zA-Z0-9_]{3,32}$/.test(username)){ //username looks OK
            request.MODEL.Users.findOne({'username':username},function(err,userFound){
              cb(err, userFound?true:false);
            });
          } else {
            cb(null,false);//username looks bad
          }
        } else {
          cb(null,false);//username is empty
        }
      },
      'email_ok':function(cb){
        var email=request.query.email;
        if(email){
          // https://github.com/chriso/node-validator/blob/master/lib/validators.js#L27
          if(/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/.test(email)){ //email looks OK
            request.MODEL.Users.findOne({'email':email},function(err,userFound){
              cb(err, userFound?true:false);
            });
          } else {
            cb(null,false);//email looks bad
          }
        } else {
          cb(null,false);//email is empty
        }
      }
    },function(err,results){
      if(err) throw err;
      response.json(results)
    });
  });

  //google works alwayes, it do not need tunning
  app.get('/auth/google', passport.authenticate('google'));
  app.get('/auth/google/return', passport.authenticate('google', { failureRedirect: '/', successRedirect: '/' }));

  //autorization by password and username
  app.post('/auth/login',passport.authenticate('local',{successRedirect: '/',failureRedirect: '/',failureFlash: true}));

  if (config.passport && config.passport.GITHUB_CLIENT_ID && config.passport.GITHUB_CLIENT_SECRET) {
    //if we have set parameters for github, enable the github passport strategy
    app.get('/auth/github', passport.authenticate('github'),
      function (req, res) {
        // The request will be redirected to GitHub for authentication, so this
        // function will not be called.
      });
    app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/' }),
      function (req, res) {
        res.redirect('/');
      });
  }

  if (config.passport && config.passport.TWITTER_CONSUMER_KEY && config.passport.TWITTER_CONSUMER_SECRET) {
    app.get('/auth/twitter', passport.authenticate('twitter'));
    app.get('/auth/twitter/callback', passport.authenticate('twitter', { successRedirect: '/', failureRedirect: '/' }));
  }

  if (config.passport && config.passport.FACEBOOK_APP_ID && config.passport.FACEBOOK_APP_SECRET) {
    app.get('/auth/facebook', passport.authenticate('facebook'));
    app.get('/auth/facebook/callback', passport.authenticate('facebook', { successRedirect: '/', failureRedirect: '/' }));
  }

  app.get('/confirm/:hash',
    passport.authenticate('hash', { failureRedirect: '/' }),
    function(req, res) {
      res.redirect('/');
    });

  app.post('/logoff', function (request, response) {
    request.logout();
    response.send(200, 'OK');
  });

}<commit_msg>[feature] logout is compatible with mwc_plugin_welcome<commit_after>var async = require('async'),
  hat = require('hat'),
  rack = hat.rack(),
  LocalStrategy = require('passport-local').Strategy,
  HashStrategy = require('passport-hash').Strategy,
  GoogleStrategy = require('passport-google').Strategy,
  GitHubStrategy = require('passport-github').Strategy,
  TwitterStrategy = require('passport-twitter').Strategy,
  FacebookStrategy = require('passport-facebook').Strategy;

exports.doInitializePassportStrategies = function (passport, Users, config) {
  //initializing passport strategies
  passport.use(new LocalStrategy(
    function (username, password, done) {
      Users.findOne({username: username, active: true}, function (err, user) {
        if (err) {
          return done(err, false, {'message': 'Database broken...'});
        } else {
          if (user) {
            if (user.verifyPassword(password)) {
              return done(null, user, {message: 'Welcome, ' + user.username});
            } else {
              return done(null, false, { message: 'Access denied!' });
            }
          } else {
            return done(null, false, { message: 'Access denied!' });
          }
        }
      });
    }
  ));

  //used for verify account by email
  passport.use(new HashStrategy(function(hash,done){
    //todo - need to refactor user class for it...
  }));

  passport.use(new GoogleStrategy({
      returnURL: config.hostUrl + 'auth/google/return',
      realm: config.hostUrl
    },
    function (identifier, profile, done) {
      var email = profile.emails[0].value;
      console.log(profile);
      Users.findOne({'email': email, active: true}, function (err, userFound) {
        console.log(userFound);
        if (userFound) {
          done(err, userFound, {message: 'Welcome, ' + userFound.username});
        } else {
          //model.UserModel.create({email:email},function(err,userCreated){
          done(err, false, { message: 'Access denied!' });//todo - i am not sure if user can register by singing in with Google Acount
          //});
        }
      });
    }
  ));

  if (config.passport && config.passport.GITHUB_CLIENT_ID && config.passport.GITHUB_CLIENT_SECRET) {
    //if we have set parameters for github, enable the github passport strategy
    passport.use(new GitHubStrategy({
      clientID: config.passport.GITHUB_CLIENT_ID,
      clientSecret: config.passport.GITHUB_CLIENT_SECRET,
      callbackURL: config.hostUrl + 'auth/github/callback'
    }, function (accessToken, refreshToken, profile, done) {
      var email = profile.emails[0].value;
      console.log(profile);
      Users.findOne({'email': email, active: true}, function (err, userFound) {
        console.log(userFound);
        if (userFound) {
          done(err, userFound, {message: 'Welcome, ' + userFound.username});
        } else {
          //model.UserModel.create({email:email},function(err,userCreated){
          done(err, false, { message: 'Access denied!' });//todo - i am not sure if user can register by singing in with Github Account
          //});
        }
      });
    }));
  }

  if (config.passport && config.passport.TWITTER_CONSUMER_KEY && config.passport.TWITTER_CONSUMER_SECRET) {
    passport.use(new TwitterStrategy({
      consumerKey: config.passport.TWITTER_CONSUMER_KEY,
      consumerSecret: config.passport.TWITTER_CONSUMER_SECRET,
      callbackURL: config.hostUrl + 'auth/twitter/callback'
    }, function (token, tokenSecret, profile, done) {
      var email = profile.emails[0].value;
      console.log(profile);
      Users.findOne({'email': email, active: true}, function (err, userFound) {
        console.log(userFound);
        if (userFound) {
          done(err, userFound, {message: 'Welcome, ' + userFound.username});
        } else {
          //model.UserModel.create({email:email},function(err,userCreated){
          done(err, false, { message: 'Access denied!' });//todo - i am not sure if user can register by singing in with Twitter Account
          //});
        }
      });
    }));
  }

  if (config.passport && config.passport.FACEBOOK_APP_ID && config.passport.FACEBOOK_APP_SECRET) {
    passport.use(new FacebookStrategy({
        clientID: config.passport.FACEBOOK_APP_ID,
        clientSecret: config.passport.FACEBOOK_APP_SECRET,
        callbackURL: config.hostUrl + 'auth/facebook/callback'
      },
      function(accessToken, refreshToken, profile, done) {
        var email = profile.emails[0].value;
        console.log(profile);
        Users.findOne({'email': email, active: true}, function (err, userFound) {
          console.log(userFound);
          if (userFound) {
            done(err, userFound, {message: 'Welcome, ' + userFound.username});
          } else {
            //model.UserModel.create({email:email},function(err,userCreated){
            done(err, false, { message: 'Access denied!' });//todo - i am not sure if user can register by singing in with Facebook Account
            //});
          }
        });
      }));
  }

  //end of initializing passport strategies

  //Storing user in session, storage key is username
  passport.serializeUser(function (user, done) {
    done(null, user.username);
  });

  passport.deserializeUser(function (username, done) {
    Users.findOne({username: username}, function (err, user) {
      done(err, user);
    });
  });
  //end of setting passport

}
exports.doInitializePassportRoutes = function (passport, app, config) {

  //registration by username, password and email
  //todo - implement the https://npmjs.org/packages/captcha
  app.post('/auth/signup',function(request,response){
    async.waterfall(
      [
        function (cb) {
          request.MODEL.Users.create({
            'username': request.body.username,
            'email': request.body.email,
            'apiKey': rack(),
            'confirmation':{
              'string':rack(),
              'date': new Date()
            }
          }, function (err, userCreated) {
            cb(err, userCreated);
          });
        },
        function (userCreatedReadyForSettingPassword, cb) {
          userCreatedReadyForSettingPassword.setPassword(request.params.password, function (err) {
            cb(err,userCreatedReadyForSettingPassword);
          });
        },
        function (userToNeNotified,cb){
          //to be implemented
          //userToNeNotified.notify()
          cb(null, true)
        }
      ], function (err, result) {
        if(err) throw err;
        if(result){
          request.flash('info','You have been registered! Please, check your email for instructions!');
          response.redirect('/');
        }
      });
  });

  //verify that login/email is not busy! - to be called by ajax
  app.get('/auth/isBusy',function(request,response){
    async.parallel({
      'username_ok':function(cb){
        var username=request.query.username;
        if(username){
          if(/^[a-zA-Z0-9_]{3,32}$/.test(username)){ //username looks OK
            request.MODEL.Users.findOne({'username':username},function(err,userFound){
              cb(err, userFound?true:false);
            });
          } else {
            cb(null,false);//username looks bad
          }
        } else {
          cb(null,false);//username is empty
        }
      },
      'email_ok':function(cb){
        var email=request.query.email;
        if(email){
          // https://github.com/chriso/node-validator/blob/master/lib/validators.js#L27
          if(/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/.test(email)){ //email looks OK
            request.MODEL.Users.findOne({'email':email},function(err,userFound){
              cb(err, userFound?true:false);
            });
          } else {
            cb(null,false);//email looks bad
          }
        } else {
          cb(null,false);//email is empty
        }
      }
    },function(err,results){
      if(err) throw err;
      response.json(results)
    });
  });

  //google works alwayes, it do not need tunning
  app.get('/auth/google', passport.authenticate('google'));
  app.get('/auth/google/return', passport.authenticate('google', { failureRedirect: '/', successRedirect: '/' }));

  //autorization by password and username
  app.post('/auth/login',passport.authenticate('local',{successRedirect: '/',failureRedirect: '/',failureFlash: true}));

  if (config.passport && config.passport.GITHUB_CLIENT_ID && config.passport.GITHUB_CLIENT_SECRET) {
    //if we have set parameters for github, enable the github passport strategy
    app.get('/auth/github', passport.authenticate('github'),
      function (req, res) {
        // The request will be redirected to GitHub for authentication, so this
        // function will not be called.
      });
    app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/' }),
      function (req, res) {
        res.redirect('/');
      });
  }

  if (config.passport && config.passport.TWITTER_CONSUMER_KEY && config.passport.TWITTER_CONSUMER_SECRET) {
    app.get('/auth/twitter', passport.authenticate('twitter'));
    app.get('/auth/twitter/callback', passport.authenticate('twitter', { successRedirect: '/', failureRedirect: '/' }));
  }

  if (config.passport && config.passport.FACEBOOK_APP_ID && config.passport.FACEBOOK_APP_SECRET) {
    app.get('/auth/facebook', passport.authenticate('facebook'));
    app.get('/auth/facebook/callback', passport.authenticate('facebook', { successRedirect: '/', failureRedirect: '/' }));
  }

  app.get('/confirm/:hash',
    passport.authenticate('hash', { failureRedirect: '/' }),
    function(req, res) {
      res.redirect('/');
    });

  app.post('/auth/logout', function (request, response) {
    request.logout();
    response.send(200, 'OK');
  });

}<|endoftext|>


<commit_before>(function($) {
    "use strict";
    var style = {
            "menuStyle": {
                "position": "absolute",
                "backgroundColor": "#ffffff",
                "opacity": "1",
                "top": "-50px",
                "right": "0px",
                "zIndex": "500",
                "color": "#000000",
                "padding": "3px",
                "border": "1px solid #000000",
                "font-family": "verdana,sans-serif",
                "font-size": "0.8em"
            }
        },
        menu = $("

")
                   .hide()
                   .css(style.menuStyle),
        mouseover = false,
        timeoutId = undefined;

    function hideMenu() {
        if (!mouseover) {
            menu.animate({ "top": "-50px" }, 100, function() { menu.hide(); });
        }
    }

    function showMenu() {
        if (timeoutId) {
            window.clearTimeout(timeoutId);
            timeoutId = undefined;
        }
        if (!menu.is(":visible")) {
            menu.show();
            menu.animate({ "top": "0px" }, 200);
        }
        timeoutId = window.setTimeout(hideMenu, 500);
    }

    function elementFor(id, label, initialState, changeHandler) {
        var ele = $("<input type='checkbox'/>").attr("id", id).attr("name", id),
            labelEle = $("").attr("for", id).text(label);

        ele.attr("checked", initialState);
        ele.bind("change", function() { changeHandler(ele.prop("checked")); });

        menu.append(ele);
        menu.append(labelEle);
        menu.append($("
"));
    }

    function buildMenuFor(entries) {
        menu.empty();
        $.each(entries, function(index, entry) {
            elementFor("flymenu-" + index, entry.label, entry.initialState, entry.changeHandler);
        });
    }

    $(document).ready(function() {
        menu.appendTo("body");
    });

    $.fn.flyMenu = function(entries) {
        buildMenuFor(entries);
        $(this).bind("mousemove", function(event) {
            if (event.pageY < 200 && event.pageX > ($("body").width() - 200)) {
                showMenu();
                return false;
            }
            return true;
        });
        menu.bind("mouseenter", function(){ mouseover = true; });
        menu.bind("mouseleave", function(){ mouseover = false; });
        return this;
    };
})(jQuery);
<commit_msg>how about a little tab to click on in order to fly-out the menu<commit_after>(function($) {
    "use strict";
    var style = {
            "menuStyle": {
                "position": "absolute",
                "backgroundColor": "#ffffff",
                "opacity": "1",
                "top": "-50px",
                "right": "0px",
                "zIndex": "500",
                "color": "#000000",
                "padding": "3px",
                "border": "1px solid #000000",
                "font-family": "verdana,sans-serif",
                "font-size": "0.8em"
            }
        },
        menuTab = $("

").hide().css(style.menuStyle),
        menu = $("

").hide().css(style.menuStyle),
        mouseover = false,
        timeoutId = undefined;

    function hideMenu() {
        if (!mouseover) {
            menu.animate({ "top": "-50px" }, 100, function() { menu.hide(); });
        }
    }

    function showMenu() {
        if (timeoutId) {
            window.clearTimeout(timeoutId);
            timeoutId = undefined;
        }
        if (!menu.is(":visible")) {
            menu.show();
            menu.animate({ "top": "0px" }, 200);
        }
        timeoutId = window.setTimeout(hideMenu, 500);
    }

    function elementFor(id, label, initialState, changeHandler) {
        var ele = $("<input type='checkbox'/>").attr("id", id).attr("name", id),
            labelEle = $("").attr("for", id).text(label);

        ele.attr("checked", initialState);
        ele.bind("change", function() { changeHandler(ele.prop("checked")); });

        menu.append(ele);
        menu.append(labelEle);
        menu.append($("
"));
    }

    function buildMenuFor(entries) {
        menu.empty();
        $.each(entries, function(index, entry) {
            elementFor("flymenu-" + index, entry.label, entry.initialState, entry.changeHandler);
        });
    }

    $(document).ready(function() {
        menu.appendTo("body");
    });

    $.fn.flyMenu = function(entries) {
        buildMenuFor(entries);
        $(this).bind("mousemove", function(event) {
            if (event.pageY < 200 && event.pageX > ($("body").width() - 200)) {
                showMenu();
                return false;
            }
            return true;
        });
        menu.bind("mouseenter", function(){ mouseover = true; });
        menu.bind("mouseleave", function(){ mouseover = false; });
        return this;
    };
})(jQuery);
<|endoftext|>


<commit_before>define('app/models/machine', ['ember'],
	/**
	 * Machine model
	 *
     * Also check state mapping in config.py
	 * @returns Class
	 */
	function() {
		return Ember.Object.extend({
			id: null,

			imageId: null,

			image: null,
			name: null,
			backend: null,
			selected: false,
			hasKey: false,
            hasMonitoring: false,
			state: 'unknown',

			reboot: function(){
				console.log('reboot');

				var that = this;

				$.ajax({
                    url: '/backends/' + this.backend.index + '/machines/' + this.id,
                    type: 'POST',
                    data: "action=reboot",
                    success: function(data) {
                    	console.log("machine rebooting");
                        that.set('state', 'rebooting');
                    }

				}).error(function(e) {
					Mist.notificationController.notify("Error rebooting machine: " + that.name);
					console.error("Error rebooting machine: " + that.name);
					console.error(e.state + " " + e.stateText);
				});
			},

			destroy: function(){
				console.log('destroy');
				$.ajax({
                    url: '/backends/' + this.backend.index + '/machines/' + this.id,
                    type: 'POST',
                    data: "action=destroy",
                    success: function(data) {
                    	console.log("machine being destroyed");
                        that.set('state', 'pending');
                    }
				}).error(function(e) {
					Mist.notificationController.notify("Error destroying machine: " + that.name);
					console.error("Error destroying machine: " + that.name);
					console.error(e.state + " " + e.stateText);
				});
			},

			start: function(){
				console.log('start');

				var that = this;

				$.ajax({
                    url: 'backends/' + this.backend.index + '/machines/' + this.id,
                    data: 'action=start',
                    type: 'POST',
                    success: function(data) {
                        console.log('machine starting');
                        that.set('state', 'pending');
                    },
                    error: function(jqXHR, textstate, errorThrown) {
                    	Mist.notificationController.notify("Error starting machine: " +
                    			that.name);
    					console.log("Error starting machine: " + that.name);
    					console.log(textstate + " " + errorThrown);
                    }
                });
			},

			shutdown: function(){
				console.log('shutting down');

				var that = this;

				$.ajax({
                    url: 'backends/' + this.backend.index + '/machines/' + this.id,
                    data: 'action=stop',
                    type: 'POST',
                    success: function(data) {
                        console.log('machine being shut down');
                        that.set('state', 'stopped');
                    },
                    error: function(jqXHR, textstate, errorThrown) {
                    	Mist.notificationController.notify("Error shutting down machine: " +
                    			that.name);
    					console.log("Error shutting down machine: " + that.name);
    					console.log(textstate + " " + errorThrown);
                    }
                });
			},

			shell: function(shell_command, callback){

				var that = this;

                console.log('Sending ' + shell_command + ' to machine: ' + that.name);

				$.ajax({
                    url: '/backends/' + this.backend.index + '/machines/' + this.id + '/shell',
                    data: {ip: this.public_ips[0],
                           command: shell_command
                           },
                    type: 'POST',
                    success: function(data) {
                        console.log("Shell command sent.Result: " + data);
                        if (data){
                            callback(data);
                        }
                    },
                    error: function(jqXHR, textstate, errorThrown) {
                    	Mist.notificationController.notify("Error sending command " + shell_command + " to machine: " +
                    			that.name);
    					console.log("Error sending shell command to machine: " + that.name);
    					console.log(textstate + " " + errorThrown);
                    }
                });

			},

			hasAlert : function(){
				//TODO when we have alerts
				return false;
			}.property('hasAlert'),

			startUptimeTimer: function(){
				var that = this;

				setInterval(function(){
					if(that.get('state' != 0) || !that.get('uptimeFromServer') || !that.get('uptimeChecked')){
						return;
					} else {
						that.set('uptime', that.get('uptimeFromServer') + (Date.now() - that.get('uptimeChecked')));
					}

				},1000);
			},

			checkUptime: function(){
				if(this.hasKey){
					var that = this;

					$.ajax({
						url: '/backends/' + this.backend.index + '/machines/' + this.id + '/uptime',
						data: {ip: this.public_ips[0]},
						success: function(data) {
							console.log("machine uptime");
							console.log(data);
							if('uptime' in data){
								that.set('uptimeChecked', Date.now());
								that.set('uptimeFromServer', data.uptime);
							}
						}
					}).error(function(jqXHR, textStatus, errorThrown) {
						console.log('error querying for machine uptime for machine id: ' + that.id);
						console.log(textStatus + " " + errorThrown);
					});
				}
			},

			checkHasMonitoring: function(){
				var that = this;

					$.ajax({
						url: 'backends/' + this.backend.index + '/machines/' + this.id + '/monitoring',
						success: function(data) {
							console.log("machine has monitoring");
							console.log(data);
							if('monitoring' in data){
								that.set('hasMonitoring', data.monitoring);
							}
						}
					}).error(function(jqXHR, textStatus, errorThrown) {
						console.log('error querying for machine monitoring for machine id: ' + that.id);
						console.log(textStatus + " " + errorThrown);
					});
			},

			checkHasKey: function(){
				var that = this;

				$.ajax({
                    url: '/backends/' + this.backend.index + '/machines/' + this.id + '/key',
                    data: {ip: this.public_ips[0]},
                    success: function(data) {
                    	console.log("machine has key? ");
                    	console.log(data);
                    	if(data){
                    		that.set('hasKey', data);
                    		that.checkUptime();
                    	} else {
                    		that.set('hasKey', false);
                    	}
                    }
				}).error(function(jqXHR, textStatus, errorThrown) {
					console.log('error querying for machine key for machine id: ' + that.id);
					console.log(textStatus + " " + errorThrown);
					that.set('hasKey', false);
				});

			},

			resetUptime: function(){
				if(this.state != 0){
					this.set('uptime', 0);
					this.uptimeTimer = false;
				} else {
					if(this.get('uptime') == 0){
						this.checkUptime();
					}
				}
			}.observes('state'),

			monitoringChanged: function(){
				var oldValue = !this.hasMonitoring;
				console.log("monitoring:  " + oldValue);

				var that = this;

				//Enable / Disable monitoring on server
				var payload = {
	                    "monitoring": this.hasMonitoring,
	            };

				$.ajax({
                    type: "POST",
                    contentType: "application/json",
                    dataType: "json",
                    data: JSON.stringify(payload),
                    url: 'backends/' + this.backend.index + '/machines/' + this.id + '/monitoring',
                    success: function(data) {

                    },
                    error: function(jqXHR, textstate, errorThrown) {
                    	that.set('hasMonitoring', oldValue);
                    }
                });

			}.observes('hasMonitoring'),

			init: function(){
				this._super();
				var that = this;
				this.backend.images.getImage(this.imageId, function(image){
					that.set('image', image);
				});
				this.startUptimeTimer();
				this.checkHasKey();
				this.checkHasMonitoring();
			}

		});
	}
);
<commit_msg>Uknown state is no longer used<commit_after>define('app/models/machine', ['ember'],
	/**
	 * Machine model
	 *
     * Also check state mapping in config.py
	 * @returns Class
	 */
	function() {
		return Ember.Object.extend({
			id: null,

			imageId: null,

			image: null,
			name: null,
			backend: null,
			selected: false,
			hasKey: false,
            hasMonitoring: false,
			state: 'stopped',

			reboot: function(){
				console.log('reboot');

				var that = this;

				$.ajax({
                    url: '/backends/' + this.backend.index + '/machines/' + this.id,
                    type: 'POST',
                    data: "action=reboot",
                    success: function(data) {
                    	console.log("machine rebooting");
                        that.set('state', 'rebooting');
                    }

				}).error(function(e) {
					Mist.notificationController.notify("Error rebooting machine: " + that.name);
					console.error("Error rebooting machine: " + that.name);
					console.error(e.state + " " + e.stateText);
				});
			},

			destroy: function(){
				console.log('destroy');
				$.ajax({
                    url: '/backends/' + this.backend.index + '/machines/' + this.id,
                    type: 'POST',
                    data: "action=destroy",
                    success: function(data) {
                    	console.log("machine being destroyed");
                        that.set('state', 'pending');
                    }
				}).error(function(e) {
					Mist.notificationController.notify("Error destroying machine: " + that.name);
					console.error("Error destroying machine: " + that.name);
					console.error(e.state + " " + e.stateText);
				});
			},

			start: function(){
				console.log('start');

				var that = this;

				$.ajax({
                    url: 'backends/' + this.backend.index + '/machines/' + this.id,
                    data: 'action=start',
                    type: 'POST',
                    success: function(data) {
                        console.log('machine starting');
                        that.set('state', 'pending');
                    },
                    error: function(jqXHR, textstate, errorThrown) {
                    	Mist.notificationController.notify("Error starting machine: " +
                    			that.name);
    					console.log("Error starting machine: " + that.name);
    					console.log(textstate + " " + errorThrown);
                    }
                });
			},

			shutdown: function(){
				console.log('shutting down');

				var that = this;

				$.ajax({
                    url: 'backends/' + this.backend.index + '/machines/' + this.id,
                    data: 'action=stop',
                    type: 'POST',
                    success: function(data) {
                        console.log('machine being shut down');
                        that.set('state', 'stopped');
                    },
                    error: function(jqXHR, textstate, errorThrown) {
                    	Mist.notificationController.notify("Error shutting down machine: " +
                    			that.name);
    					console.log("Error shutting down machine: " + that.name);
    					console.log(textstate + " " + errorThrown);
                    }
                });
			},

			shell: function(shell_command, callback){

				var that = this;

                console.log('Sending ' + shell_command + ' to machine: ' + that.name);

				$.ajax({
                    url: '/backends/' + this.backend.index + '/machines/' + this.id + '/shell',
                    data: {ip: this.public_ips[0],
                           command: shell_command
                           },
                    type: 'POST',
                    success: function(data) {
                        console.log("Shell command sent.Result: " + data);
                        if (data){
                            callback(data);
                        }
                    },
                    error: function(jqXHR, textstate, errorThrown) {
                    	Mist.notificationController.notify("Error sending command " + shell_command + " to machine: " +
                    			that.name);
    					console.log("Error sending shell command to machine: " + that.name);
    					console.log(textstate + " " + errorThrown);
                    }
                });

			},

			hasAlert : function(){
				//TODO when we have alerts
				return false;
			}.property('hasAlert'),

			startUptimeTimer: function(){
				var that = this;

				setInterval(function(){
					if(that.get('state' != 0) || !that.get('uptimeFromServer') || !that.get('uptimeChecked')){
						return;
					} else {
						that.set('uptime', that.get('uptimeFromServer') + (Date.now() - that.get('uptimeChecked')));
					}

				},1000);
			},

			checkUptime: function(){
				if(this.hasKey){
					var that = this;

					$.ajax({
						url: '/backends/' + this.backend.index + '/machines/' + this.id + '/uptime',
						data: {ip: this.public_ips[0]},
						success: function(data) {
							console.log("machine uptime");
							console.log(data);
							if('uptime' in data){
								that.set('uptimeChecked', Date.now());
								that.set('uptimeFromServer', data.uptime);
							}
						}
					}).error(function(jqXHR, textStatus, errorThrown) {
						console.log('error querying for machine uptime for machine id: ' + that.id);
						console.log(textStatus + " " + errorThrown);
					});
				}
			},

			checkHasMonitoring: function(){
				var that = this;

					$.ajax({
						url: 'backends/' + this.backend.index + '/machines/' + this.id + '/monitoring',
						success: function(data) {
							console.log("machine has monitoring");
							console.log(data);
							if('monitoring' in data){
								that.set('hasMonitoring', data.monitoring);
							}
						}
					}).error(function(jqXHR, textStatus, errorThrown) {
						console.log('error querying for machine monitoring for machine id: ' + that.id);
						console.log(textStatus + " " + errorThrown);
					});
			},

			checkHasKey: function(){
				var that = this;

				$.ajax({
                    url: '/backends/' + this.backend.index + '/machines/' + this.id + '/key',
                    data: {ip: this.public_ips[0]},
                    success: function(data) {
                    	console.log("machine has key? ");
                    	console.log(data);
                    	if(data){
                    		that.set('hasKey', data);
                    		that.checkUptime();
                    	} else {
                    		that.set('hasKey', false);
                    	}
                    }
				}).error(function(jqXHR, textStatus, errorThrown) {
					console.log('error querying for machine key for machine id: ' + that.id);
					console.log(textStatus + " " + errorThrown);
					that.set('hasKey', false);
				});

			},

			resetUptime: function(){
				if(this.state != 0){
					this.set('uptime', 0);
					this.uptimeTimer = false;
				} else {
					if(this.get('uptime') == 0){
						this.checkUptime();
					}
				}
			}.observes('state'),

			monitoringChanged: function(){
				var oldValue = !this.hasMonitoring;
				console.log("monitoring:  " + oldValue);

				var that = this;

				//Enable / Disable monitoring on server
				var payload = {
	                    "monitoring": this.hasMonitoring,
	            };

				$.ajax({
                    type: "POST",
                    contentType: "application/json",
                    dataType: "json",
                    data: JSON.stringify(payload),
                    url: 'backends/' + this.backend.index + '/machines/' + this.id + '/monitoring',
                    success: function(data) {

                    },
                    error: function(jqXHR, textstate, errorThrown) {
                    	that.set('hasMonitoring', oldValue);
                    }
                });

			}.observes('hasMonitoring'),

			init: function(){
				this._super();
				var that = this;
				this.backend.images.getImage(this.imageId, function(image){
					that.set('image', image);
				});
				this.startUptimeTimer();
				this.checkHasKey();
				this.checkHasMonitoring();
			}

		});
	}
);
<|endoftext|>


<commit_before>import store, { getModule } from './../../store/index.js';

const { getters, configuration } = getModule('segmentation');

/**
 * Called by the event dispatcher to render the image.
 *
 * @param {Object} evt - The event.
 * @returns {void}
 */
export default function renderBrush(evt) {
  const eventData = evt.detail;
  const viewport = eventData.viewport;

  let mousePosition;

  if (this._drawing) {
    mousePosition = this._lastImageCoords;
  } else if (this._mouseUpRender) {
    mousePosition = this._lastImageCoords;
    this._mouseUpRender = false;
  } else {
    mousePosition = store.state.mousePositionImage;
  }

  if (!mousePosition) {
    return;
  }

  const { rows, columns } = eventData.image;
  const { x, y } = mousePosition;

  if (x < 0 || x > columns || y < 0 || y > rows) {
    return;
  }

  // Draw the hover overlay on top of the pixel data
  const radius = configuration.radius;
  const context = eventData.canvasContext;
  const element = eventData.element;
  const color = getters.brushColor(element, this._drawing);

  context.setTransform(1, 0, 0, 1, 0, 0);

  const { cornerstone } = external;

  const circleRadius = radius * viewport.scale;
  const mouseCoordsCanvas = cornerstone.pixelToCanvas(element, mousePosition);

  context.beginPath();
  context.strokeStyle = color;
  context.ellipse(
    mouseCoordsCanvas.x,
    mouseCoordsCanvas.y,
    circleRadius,
    circleRadius,
    0,
    0,
    2 * Math.PI
  );
  context.stroke();
}
<commit_msg>Export as an object, not a func<commit_after>import store, { getModule } from './../../store/index.js';

const { getters, configuration } = getModule('segmentation');

/**
 * Called by the event dispatcher to render the image.
 *
 * @param {Object} evt - The event.
 * @returns {void}
 */
function renderBrush(evt) {
  const eventData = evt.detail;
  const viewport = eventData.viewport;

  let mousePosition;

  if (this._drawing) {
    mousePosition = this._lastImageCoords;
  } else if (this._mouseUpRender) {
    mousePosition = this._lastImageCoords;
    this._mouseUpRender = false;
  } else {
    mousePosition = store.state.mousePositionImage;
  }

  if (!mousePosition) {
    return;
  }

  const { rows, columns } = eventData.image;
  const { x, y } = mousePosition;

  if (x < 0 || x > columns || y < 0 || y > rows) {
    return;
  }

  // Draw the hover overlay on top of the pixel data
  const radius = configuration.radius;
  const context = eventData.canvasContext;
  const element = eventData.element;
  const color = getters.brushColor(element, this._drawing);

  context.setTransform(1, 0, 0, 1, 0, 0);

  const { cornerstone } = external;

  const circleRadius = radius * viewport.scale;
  const mouseCoordsCanvas = cornerstone.pixelToCanvas(element, mousePosition);

  context.beginPath();
  context.strokeStyle = color;
  context.ellipse(
    mouseCoordsCanvas.x,
    mouseCoordsCanvas.y,
    circleRadius,
    circleRadius,
    0,
    0,
    2 * Math.PI
  );
  context.stroke();
}

export default {
  renderBrush,
};
<|endoftext|>


<commit_before>export { Base };

import * as ValueDesc from "../Unpacker/ValueDesc.js";
import * as ActivationEscaping from "./ActivationEscaping.js";
import * as BoundsArraySet from "./BoundsArraySet.js";
import * as Depthwise from "./Depthwise.js";
import * as Pointwise from "./Pointwise.js";

//!!! ...unfinished... (2022/05/15)
// Fo half copy and pass-through, the squeeze and excitation should also pass-through
// (i.e filter = 0, bias = 1) (compare to pass-through for addition operation: filter = 1, bias = 0)
//
// pointwiseSE's filterValueAdjusted = undoDepthwiseActivationEscapingScale * filterValue
//
// pointwise2's filterValueAdjusted = undoDepthwiseActivationEscapingScale * undoPointwiseSEActivationEscapingScale * filterValue
//
//
//
// o should undo previous activation escaping scale
// o when pass-through, filter = 0, bias = 1 (not: filter 1, bias 0)
// o even if there is pass-through, it is not necessary to activation escaping scale.
// o The bounds array set of output (which is input multiplied by squeeze-and-excitation) should include squeeze-and-excitation.
//   However, the activation escaping scale should be the same as input's activation escaping scale.
//   So that the next operation (e.g. pointwise2) could restore the correct input (with squeeze-and-excitation) 。
//
// PASS_THROUGH_STYLE_FILTER_1_BIAS_0_ACTIVATION_ESCAPING
// PASS_THROUGH_STYLE_FILTER_0_BIAS_1_ACTIVATION_NO_ESCAPING

/**
 *
 * @member {number} byteOffsetBegin
 *   The position which is started (inclusive) to extract from inputFloat32Array.buffer by init(). This is relative to the
 * inputFloat32Array.buffer (not to the inputFloat32Array.byteOffset).
 *
 * @member {number} byteOffsetEnd
 *   The position which is ended to (non-inclusive) extract from inputFloat32Array.buffer by init(). Where to extract next weights.
 * Only meaningful when ( this.bInitOk == true ). This is relative to the inputFloat32Array.buffer (not to the inputFloat32Array.byteOffset).
 *
 * @member {number} inputChannelCount
 *   The channel count of the input tensor. It must be greater than zero (> 0).
 *
 * @member {number} intermediateChannelCount
 *   The channel count between squeeze and excitation.
 *
 *     - If ( intermediateChannelCount <= 0 ), there will be only one pointwise convolution (i.e. excitation pointwise convolution).
 *
 *     - If ( intermediateChannelCount > 0 ), there will be two pointwise convolutions (i.e. pointwise convolution before
 *         excitation, and excitation pointwise convolution).
 *
 * @member {number} outputChannelCount
 *   Always the same as inputChannelCount.
 *
 * @member {ValueDesc.Pointwise_HigherHalfDifferent} nHigherHalfDifferent
 *   The HigherHalfDifferent type for pointwise convolution in squeeze-and-excitation.
 *
 * @member {number} tensorWeightCountTotal
 *   The total wieght count used in tensors. Including inferenced weights, if they are used in tensors.
 *
 * @member {number} tensorWeightCountExtracted
 *   The wieght count extracted from inputFloat32Array and used in tensors. Not including inferenced weights (even if they are
 * used in tensors), because they are not extracted from inputFloat32Array.
 *
 * @member {function} pfnSqueezeExcitation
 *   A method accepts one parameter inputTensor (tf.tensor3d) and return an outputTensor (tf.tensor3d). All intermediate tensors
 * will be disposed. The inputTensor may or may not be disposed (according to setKeepInputTensor()). In fact, this method calls one
 * of Base.Xxx_and_keep() according to the parameters.
 *
 */
class Base {

//!!! ...unfinished... (2022/05/18)
// Perhaps, rename excitationPointwise to excitationPointwise2, and intermediatePointwise to excitationPointwise1.

  /**
   *
   */
  constructor(
    inputChannelCount, intermediateChannelCount, bBias, nActivationId,
    nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf ) {

    tf.util.assert( ( inputChannelCount > 0 ),
      `SqueezeExcitation.constructor(): `
        + `inputChannelCount ( ${inputChannelCount} ) should be greater than zero (> 0).`
    );

    // Note: Inside squeeze-and-excitation, all depthwsie and pointwise convolutions are constnat-when-pass-through.
    //       So that the result for pass-through parts will not affect input when multiply to input.
    //

//!!! ...unfinished... (2022/05/18) bBias?
//  If no activation, it is enough to let the only last operation have ( bBias == true ).
//

//!!! ...unfinished... (2022/05/18) squeeze?
    if (  ) {
      this.squeezeDepthwise = new Depthwise.ConstantWhenPassThrough(

  //!!! ...unfinished... (2022/05/18)
        inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth,

        ???ValueDesc.StridesPad.Singleton.STRIDES_1_PAD_SAME, // (stridesPad)

        bBias, nActivationId, nPassThroughStyleId,
        nHigherHalfDifferent, inputChannelCount_lowerHalf
      );
    }

    this.intermediateChannelCount = intermediateChannelCount;
    if ( intermediateChannelCount > 0 ) {
      this.intermediatePointwise = new Pointwise.ConstantWhenPassThrough(
        inputChannelCount,
        intermediateChannelCount,
        bBias, nActivationId,
        nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf,
        0, // Inside squeeze-and-excitation, never shuffle channels. ( channelShuffler_outputGroupCount == 0 ).
      );
    }

    this.excitationPointwise = new Pointwise.ConstantWhenPassThrough(
      intermediateChannelCount,
      inputChannelCount, // For squeeze-and-excitation, output channel count always the same as input.
      bBias, nActivationId,
      nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf,
      0, // Inside squeeze-and-excitation, never shuffle channels. ( channelShuffler_outputGroupCount == 0 ).
    );

  }

  /**
   * @param {Float32Array} inputFloat32Array
   *   A Float32Array whose values will be interpreted as weights.
   *
   * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray
   *   The element value bounds (per channel) of input. Usually, it is The .output of the previous operation value bounds set
   * of this operation. It will be kept (not cloned) directly. So caller should not modify them.
   *
   * @return {boolean} Return true, if succeeded.
   */
  init( inputFloat32Array, byteOffsetBegin, inputScaleBoundsArray ) {

    this.disposeTensors();

    this.byteOffsetBegin = this.byteOffsetEnd = byteOffsetBegin;

    // 1. Determine operation functions.
    Base.setup_pfnSqueezeExcitation.call( this );

    // 2. Initialize sub-operations.

    // 2.1
    let squeezeDepthwise_boundsArraySet_output0;
    if ( this.squeezeDepthwise ) {
      if ( !this.squeezeDepthwise.init( inputFloat32Array, this.byteOffsetEnd, inputScaleBoundsArray ) )
        return false;  // e.g. input array does not have enough data.
      this.byteOffsetEnd = this.squeezeDepthwise.byteOffsetEnd;

      this.tensorWeightCountTotal += this.squeezeDepthwise.tensorWeightCountTotal;
      this.tensorWeightCountExtracted += this.squeezeDepthwise.tensorWeightCountExtracted;

      squeezeDepthwise_boundsArraySet_output0 = this.squeezeDepthwise.boundsArraySet.output0;
    } else {
      squeezeDepthwise_boundsArraySet_output0 = inputScaleBoundsArray;
    }

    // 2.2
    let intermediatePointwise_boundsArraySet_output0;
    if ( this.intermediatePointwise ) {
      if ( !this.intermediatePointwise.init( inputFloat32Array, this.byteOffsetEnd, squeezeDepthwise_boundsArraySet_output0 ) )
        return false;  // e.g. input array does not have enough data.
      this.byteOffsetEnd = this.intermediatePointwise.byteOffsetEnd;

      this.tensorWeightCountTotal += this.intermediatePointwise.tensorWeightCountTotal;
      this.tensorWeightCountExtracted += this.intermediatePointwise.tensorWeightCountExtracted;

      intermediatePointwise_boundsArraySet_output0 = this.intermediatePointwise.boundsArraySet.output0;
    } else {
      intermediatePointwise_boundsArraySet_output0 = squeezeDepthwise_boundsArraySet_output0;
    }

    // 2.3
    {
      if ( !this.excitationPointwise.init( inputFloat32Array, this.byteOffsetEnd, intermediatePointwise_boundsArraySet_output0 ) )
        return false;  // e.g. input array does not have enough data.
      this.byteOffsetEnd = this.excitationPointwise.byteOffsetEnd;

      this.tensorWeightCountTotal += this.excitationPointwise.tensorWeightCountTotal;
      this.tensorWeightCountExtracted += this.excitationPointwise.tensorWeightCountExtracted;
    }

    // 3. BoundsArraySet
    {
      { // Build self BoundsArraySet.
        this.boundsArraySet = new BoundsArraySet.InputsOutputs( inputScaleBoundsArray, null,
          this.excitationPointwise.boundsArraySet.output0.channelCount, 0 );

        this.boundsArraySet.set_outputs_all_byBoundsArraySet_Outputs( this.excitationPointwise.boundsArraySet );

        // The BoundsArraySet for tf.mul() input by excitation.
        //
        // Note: Not multiply_all_byScaleBoundsArray_one(). The reason is that it is supported to broadcast in the same channel
        // (i.e. not across channels).
        //
        this.boundsArraySet.output0.multiply_all_byScaleBoundsArray_all( inputScaleBoundsArray );
      }

      this.dispose_all_sub_BoundsArraySet(); // For reduce memory footprint.
    }

    this.bInitOk = true;
    return this.bInitOk;
  }

  /** Release all tensors. */
  disposeTensors() {
    if ( this.squeezeDepthwise ) {
      this.squeezeDepthwise.disposeTensors();
      this.squeezeDepthwise = null;
    }

    if ( this.intermediatePointwise ) {
      this.intermediatePointwise.disposeTensors();
      this.intermediatePointwise = null;
    }

    if ( this.excitationPointwise ) {
      this.excitationPointwise.disposeTensors();
      this.excitationPointwise = null;
    }

    this.tensorWeightCountTotal = this.tensorWeightCountExtracted = 0;
    this.byteOffsetBegin = this.byteOffsetEnd = -1;
    this.bKeepInputTensor = false;  // Default will dispose input tensor.
    this.bInitOk = false;
  }

  /**
   * Release all BoundsArraySet of squeezeDepthwise, intermediatePointwise, excitationPointwise.
   *
   * This could reduce memory footprint.
   *
   * (Note: This SqueezeExcitation's BoundsArraySet is kept.)
   */
  dispose_all_sub_BoundsArraySet() {
    delete this.squeezeDepthwise?.boundsArraySet;
    delete this.intermediatePointwise?.boundsArraySet;
    delete this.excitationPointwise.boundsArraySet;
  }

  /**
   * Adjust this.pfnSqueezeExcitation_and_destroy_or_keep so that it is either:
   *   - the same as this.pfnSqueezeExcitation_and_keep which will not dispose inputTensor. or,
   *   - pointer to Base.operation_and_destroy() which will dispose inputTensor.
   *
   * The sub operations' setKeepInputTensor() will also be called.
   *
   */
  setKeepInputTensor( bKeepInputTensor ) {
    if ( bKeepInputTensor == this.bKeepInputTensor )
      return;

    this.bKeepInputTensor = bKeepInputTensor;
    if ( bKeepInputTensor ) {

      // Note: The first operation is responsible for keep inputTensor. All other operations should always destroy inputTensor.
      if ( this.squeezeDepthwise ) {
        this.squeezeDepthwise.setKeepInputTensor( true );
        this.intermediatePointwise.setKeepInputTensor( false );
        this.excitationPointwise.setKeepInputTensor( false );
      } else {
        if ( this.intermediatePointwise ) {
          this.intermediatePointwise.setKeepInputTensor( true );
          this.excitationPointwise.setKeepInputTensor( false );
        } else {
          this.excitationPointwise.setKeepInputTensor( true );
        }
      }

    } else {
      this.squeezeDepthwise?.setKeepInputTensor( false );
      this.intermediatePointwise?.setKeepInputTensor( false );
      this.excitationPointwise.setKeepInputTensor( false );
    }
  }

  /** Determine data member this.pfnSqueezeExcitation.
   *
   * @param {Base} this
   *   The Base object to be determined and modified.
   */
  static setup_pfnSqueezeExcitation() {
    if ( this.squeezeDepthwise ) {
      if ( this.intermediatePointwise ) {
        this.pfnSqueezeExcitation = Base.squeeze_intermediate_excitation;
      } else {
        this.pfnSqueezeExcitation = Base.squeeze_excitation;
      }
    } else {
      if ( this.intermediatePointwise ) {
        this.pfnSqueezeExcitation = Base.intermediate_excitation;
      } else {
        this.pfnSqueezeExcitation = Base.excitation;
      }
    }
  }

  /** */
  static squeeze_intermediate_excitation( inputTensor ) {
    let t0, t1;
    t0 = this.squeezeDepthwise.pfnOperationBiasActivation( inputTensor );
    t1 = this.intermediatePointwise.pfnConvBiasActivation( t0 );
    t0 = this.excitationPointwise.pfnConvBiasActivation( t1 );

    t1 = tf.mul( inputTensor, t0 );
    t0.dispose();
    return t1;
  }

  /** */
  static squeeze_excitation_and_keep( inputTensor ) {
    let t0, t1;
    t0 = this.squeezeDepthwise.pfnOperationBiasActivation( inputTensor );
    t1 = this.excitationPointwise.pfnConvBiasActivation( t0 );

    t0 = tf.mul( inputTensor, t1 );
    t1.dispose();
    return t0;
  }

  /** */
  static intermediate_excitation_and_keep( inputTensor ) {
    let t0, t1;
    t0 = this.intermediatePointwise.pfnConvBiasActivation( inputTensor );
    t1 = this.excitationPointwise.pfnConvBiasActivation( t0 );

    t0 = tf.mul( inputTensor, t1 );
    t1.dispose();
    return t0;
  }

  /** */
  static excitation_and_keep( inputTensor ) {
    let t0, t1;
    t0 = this.excitationPointwise.pfnConvBiasActivation( inputTensor );

    t1 = tf.mul( inputTensor, t0 );
    t0.dispose();
    return t1;
  }

}
<commit_msg>Update SqueezeExcitation.js<commit_after>export { Base };

import * as ValueDesc from "../Unpacker/ValueDesc.js";
import * as ActivationEscaping from "./ActivationEscaping.js";
import * as BoundsArraySet from "./BoundsArraySet.js";
import * as Depthwise from "./Depthwise.js";
import * as Pointwise from "./Pointwise.js";

//!!! ...unfinished... (2022/05/15)
// Fo half copy and pass-through, the squeeze and excitation should also pass-through
// (i.e filter = 0, bias = 1) (compare to pass-through for addition operation: filter = 1, bias = 0)
//
// pointwiseSE's filterValueAdjusted = undoDepthwiseActivationEscapingScale * filterValue
//
// pointwise2's filterValueAdjusted = undoDepthwiseActivationEscapingScale * undoPointwiseSEActivationEscapingScale * filterValue
//
//
//
// o should undo previous activation escaping scale
// o when pass-through, filter = 0, bias = 1 (not: filter 1, bias 0)
// o even if there is pass-through, it is not necessary to activation escaping scale.
// o The bounds array set of output (which is input multiplied by squeeze-and-excitation) should include squeeze-and-excitation.
//   However, the activation escaping scale should be the same as input's activation escaping scale.
//   So that the next operation (e.g. pointwise2) could restore the correct input (with squeeze-and-excitation) 。
//
// PASS_THROUGH_STYLE_FILTER_1_BIAS_0_ACTIVATION_ESCAPING
// PASS_THROUGH_STYLE_FILTER_0_BIAS_1_ACTIVATION_NO_ESCAPING

/**
 *
 * @member {number} byteOffsetBegin
 *   The position which is started (inclusive) to extract from inputFloat32Array.buffer by init(). This is relative to the
 * inputFloat32Array.buffer (not to the inputFloat32Array.byteOffset).
 *
 * @member {number} byteOffsetEnd
 *   The position which is ended to (non-inclusive) extract from inputFloat32Array.buffer by init(). Where to extract next weights.
 * Only meaningful when ( this.bInitOk == true ). This is relative to the inputFloat32Array.buffer (not to the inputFloat32Array.byteOffset).
 *
 * @member {number} inputChannelCount
 *   The channel count of the input tensor. It must be greater than zero (> 0).
 *
 * @member {number} intermediateChannelCount
 *   The channel count between squeeze and excitation.
 *
 *     - If ( intermediateChannelCount <= 0 ), there will be only one pointwise convolution (i.e. excitation pointwise convolution).
 *
 *     - If ( intermediateChannelCount > 0 ), there will be two pointwise convolutions (i.e. pointwise convolution before
 *         excitation, and excitation pointwise convolution).
 *
 * @member {number} outputChannelCount
 *   Always the same as inputChannelCount.
 *
 * @member {ValueDesc.Pointwise_HigherHalfDifferent} nHigherHalfDifferent
 *   The HigherHalfDifferent type for pointwise convolution in squeeze-and-excitation.
 *
 * @member {number} tensorWeightCountTotal
 *   The total wieght count used in tensors. Including inferenced weights, if they are used in tensors.
 *
 * @member {number} tensorWeightCountExtracted
 *   The wieght count extracted from inputFloat32Array and used in tensors. Not including inferenced weights (even if they are
 * used in tensors), because they are not extracted from inputFloat32Array.
 *
 * @member {function} pfnSqueezeExcitation
 *   A method accepts one parameter inputTensor (tf.tensor3d) and return an outputTensor (tf.tensor3d). All intermediate tensors
 * will be disposed. The inputTensor may or may not be disposed (according to setKeepInputTensor()). In fact, this method calls one
 * of Base.Xxx_and_keep() according to the parameters.
 *
 */
class Base {

//!!! ...unfinished... (2022/05/18)
// Perhaps, rename excitationPointwise to excitation2Pointwise, and intermediatePointwise to excitation1Pointwise.

  /**
   *
   */
  constructor(
    inputChannelCount, intermediateChannelCount, bBias, nActivationId,
    nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf ) {

    tf.util.assert( ( inputChannelCount > 0 ),
      `SqueezeExcitation.constructor(): `
        + `inputChannelCount ( ${inputChannelCount} ) should be greater than zero (> 0).`
    );

    // Note: Inside squeeze-and-excitation, all depthwsie and pointwise convolutions are constnat-when-pass-through.
    //       So that the result for pass-through parts will not affect input when multiply to input.
    //

//!!! ...unfinished... (2022/05/18) bBias?
//  If no activation, it is enough to let the only last operation have ( bBias == true ).
//

//!!! ...unfinished... (2022/05/18) squeeze?
    if (  ) {
      this.squeezeDepthwise = new Depthwise.ConstantWhenPassThrough(

  //!!! ...unfinished... (2022/05/18)
        inputHeight, inputWidth, inputChannelCount, AvgMax_Or_ChannelMultiplier, filterHeight, filterWidth,

        ???ValueDesc.StridesPad.Singleton.STRIDES_1_PAD_SAME, // (stridesPad)

        bBias, nActivationId, nPassThroughStyleId,
        nHigherHalfDifferent, inputChannelCount_lowerHalf
      );
    }

    this.intermediateChannelCount = intermediateChannelCount;
    if ( intermediateChannelCount > 0 ) {
      this.intermediatePointwise = new Pointwise.ConstantWhenPassThrough(
        inputChannelCount,
        intermediateChannelCount,
        bBias, nActivationId,
        nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf,
        0, // Inside squeeze-and-excitation, never shuffle channels. ( channelShuffler_outputGroupCount == 0 ).
      );
    }

    this.excitationPointwise = new Pointwise.ConstantWhenPassThrough(
      intermediateChannelCount,
      inputChannelCount, // For squeeze-and-excitation, output channel count always the same as input.
      bBias, nActivationId,
      nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf,
      0, // Inside squeeze-and-excitation, never shuffle channels. ( channelShuffler_outputGroupCount == 0 ).
    );

  }

  /**
   * @param {Float32Array} inputFloat32Array
   *   A Float32Array whose values will be interpreted as weights.
   *
   * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray
   *   The element value bounds (per channel) of input. Usually, it is The .output of the previous operation value bounds set
   * of this operation. It will be kept (not cloned) directly. So caller should not modify them.
   *
   * @return {boolean} Return true, if succeeded.
   */
  init( inputFloat32Array, byteOffsetBegin, inputScaleBoundsArray ) {

    this.disposeTensors();

    this.byteOffsetBegin = this.byteOffsetEnd = byteOffsetBegin;

    // 1. Determine operation functions.
    Base.setup_pfnSqueezeExcitation.call( this );

    // 2. Initialize sub-operations.

    // 2.1
    let squeezeDepthwise_boundsArraySet_output0;
    if ( this.squeezeDepthwise ) {
      if ( !this.squeezeDepthwise.init( inputFloat32Array, this.byteOffsetEnd, inputScaleBoundsArray ) )
        return false;  // e.g. input array does not have enough data.
      this.byteOffsetEnd = this.squeezeDepthwise.byteOffsetEnd;

      this.tensorWeightCountTotal += this.squeezeDepthwise.tensorWeightCountTotal;
      this.tensorWeightCountExtracted += this.squeezeDepthwise.tensorWeightCountExtracted;

      squeezeDepthwise_boundsArraySet_output0 = this.squeezeDepthwise.boundsArraySet.output0;
    } else {
      squeezeDepthwise_boundsArraySet_output0 = inputScaleBoundsArray;
    }

    // 2.2
    let intermediatePointwise_boundsArraySet_output0;
    if ( this.intermediatePointwise ) {
      if ( !this.intermediatePointwise.init( inputFloat32Array, this.byteOffsetEnd, squeezeDepthwise_boundsArraySet_output0 ) )
        return false;  // e.g. input array does not have enough data.
      this.byteOffsetEnd = this.intermediatePointwise.byteOffsetEnd;

      this.tensorWeightCountTotal += this.intermediatePointwise.tensorWeightCountTotal;
      this.tensorWeightCountExtracted += this.intermediatePointwise.tensorWeightCountExtracted;

      intermediatePointwise_boundsArraySet_output0 = this.intermediatePointwise.boundsArraySet.output0;
    } else {
      intermediatePointwise_boundsArraySet_output0 = squeezeDepthwise_boundsArraySet_output0;
    }

    // 2.3
    {
      if ( !this.excitationPointwise.init( inputFloat32Array, this.byteOffsetEnd, intermediatePointwise_boundsArraySet_output0 ) )
        return false;  // e.g. input array does not have enough data.
      this.byteOffsetEnd = this.excitationPointwise.byteOffsetEnd;

      this.tensorWeightCountTotal += this.excitationPointwise.tensorWeightCountTotal;
      this.tensorWeightCountExtracted += this.excitationPointwise.tensorWeightCountExtracted;
    }

    // 3. BoundsArraySet
    {
      { // Build self BoundsArraySet.
        this.boundsArraySet = new BoundsArraySet.InputsOutputs( inputScaleBoundsArray, null,
          this.excitationPointwise.boundsArraySet.output0.channelCount, 0 );

        this.boundsArraySet.set_outputs_all_byBoundsArraySet_Outputs( this.excitationPointwise.boundsArraySet );

        // The BoundsArraySet for tf.mul() input by excitation.
        //
        // Note: Not multiply_all_byScaleBoundsArray_one(). The reason is that it is supported to broadcast in the same channel
        // (i.e. not across channels).
        //
        this.boundsArraySet.output0.multiply_all_byScaleBoundsArray_all( inputScaleBoundsArray );
      }

      this.dispose_all_sub_BoundsArraySet(); // For reduce memory footprint.
    }

    this.bInitOk = true;
    return this.bInitOk;
  }

  /** Release all tensors. */
  disposeTensors() {
    if ( this.squeezeDepthwise ) {
      this.squeezeDepthwise.disposeTensors();
      this.squeezeDepthwise = null;
    }

    if ( this.intermediatePointwise ) {
      this.intermediatePointwise.disposeTensors();
      this.intermediatePointwise = null;
    }

    if ( this.excitationPointwise ) {
      this.excitationPointwise.disposeTensors();
      this.excitationPointwise = null;
    }

    this.tensorWeightCountTotal = this.tensorWeightCountExtracted = 0;
    this.byteOffsetBegin = this.byteOffsetEnd = -1;
    this.bKeepInputTensor = false;  // Default will dispose input tensor.
    this.bInitOk = false;
  }

  /**
   * Release all BoundsArraySet of squeezeDepthwise, intermediatePointwise, excitationPointwise.
   *
   * This could reduce memory footprint.
   *
   * (Note: This SqueezeExcitation's BoundsArraySet is kept.)
   */
  dispose_all_sub_BoundsArraySet() {
    delete this.squeezeDepthwise?.boundsArraySet;
    delete this.intermediatePointwise?.boundsArraySet;
    delete this.excitationPointwise.boundsArraySet;
  }

  /**
   * Adjust this.pfnSqueezeExcitation_and_destroy_or_keep so that it is either:
   *   - the same as this.pfnSqueezeExcitation_and_keep which will not dispose inputTensor. or,
   *   - pointer to Base.operation_and_destroy() which will dispose inputTensor.
   *
   * The sub operations' setKeepInputTensor() will also be called.
   *
   */
  setKeepInputTensor( bKeepInputTensor ) {
    if ( bKeepInputTensor == this.bKeepInputTensor )
      return;

    this.bKeepInputTensor = bKeepInputTensor;
    if ( bKeepInputTensor ) {

      // Note: The first operation is responsible for keep inputTensor. All other operations should always destroy inputTensor.
      if ( this.squeezeDepthwise ) {
        this.squeezeDepthwise.setKeepInputTensor( true );
        this.intermediatePointwise.setKeepInputTensor( false );
        this.excitationPointwise.setKeepInputTensor( false );
      } else {
        if ( this.intermediatePointwise ) {
          this.intermediatePointwise.setKeepInputTensor( true );
          this.excitationPointwise.setKeepInputTensor( false );
        } else {
          this.excitationPointwise.setKeepInputTensor( true );
        }
      }

    } else {
      this.squeezeDepthwise?.setKeepInputTensor( false );
      this.intermediatePointwise?.setKeepInputTensor( false );
      this.excitationPointwise.setKeepInputTensor( false );
    }
  }

  /** Determine data member this.pfnSqueezeExcitation.
   *
   * @param {Base} this
   *   The Base object to be determined and modified.
   */
  static setup_pfnSqueezeExcitation() {
    if ( this.squeezeDepthwise ) {
      if ( this.intermediatePointwise ) {
        this.pfnSqueezeExcitation = Base.squeeze_intermediate_excitation;
      } else {
        this.pfnSqueezeExcitation = Base.squeeze_excitation;
      }
    } else {
      if ( this.intermediatePointwise ) {
        this.pfnSqueezeExcitation = Base.intermediate_excitation;
      } else {
        this.pfnSqueezeExcitation = Base.excitation;
      }
    }
  }

  /** */
  static squeeze_intermediate_excitation( inputTensor ) {
    let t0, t1;
    t0 = this.squeezeDepthwise.pfnOperationBiasActivation( inputTensor );
    t1 = this.intermediatePointwise.pfnConvBiasActivation( t0 );
    t0 = this.excitationPointwise.pfnConvBiasActivation( t1 );

    t1 = tf.mul( inputTensor, t0 );
    t0.dispose();
    return t1;
  }

  /** */
  static squeeze_excitation_and_keep( inputTensor ) {
    let t0, t1;
    t0 = this.squeezeDepthwise.pfnOperationBiasActivation( inputTensor );
    t1 = this.excitationPointwise.pfnConvBiasActivation( t0 );

    t0 = tf.mul( inputTensor, t1 );
    t1.dispose();
    return t0;
  }

  /** */
  static intermediate_excitation_and_keep( inputTensor ) {
    let t0, t1;
    t0 = this.intermediatePointwise.pfnConvBiasActivation( inputTensor );
    t1 = this.excitationPointwise.pfnConvBiasActivation( t0 );

    t0 = tf.mul( inputTensor, t1 );
    t1.dispose();
    return t0;
  }

  /** */
  static excitation_and_keep( inputTensor ) {
    let t0, t1;
    t0 = this.excitationPointwise.pfnConvBiasActivation( inputTensor );

    t1 = tf.mul( inputTensor, t0 );
    t0.dispose();
    return t1;
  }

}
<|endoftext|>


<commit_before>export { Base };

/**
 * A placeholder for tensor.
 *
 *   - In Operation.TwinArray.operation_append_Xxx(), it is used for tracking a tensor's final operation which should be responsible
 *       for destroying the tensor.
 *
 *   - In operation's .apply(), it is used for transferring tensor to the next sub operation.
 *
 *
 * @member {Operation.Base} finalOperationOld
 *   The previous finalOperation. When new finalOperation is set, the finalOperationOld.setKeepInputTensor_IfNotLastOperation_Or_In()
 * usually should be called to adjust tensor destroying behavior (since it is no longer the final operation of the tensor).
 *
 * @member {Operation.Base} finalOperation
 *   The operation uses this tensor at final. It should be responsible for destroying this tensor. If null, this tensor is
 * not used by any operation.
 *
 * @member {tf.tensor} realTensor
 *   The real tensor represented by this placeholder. It is filled dynamically in an operation's apply() method.
 *
 */
class Base {

  /**
   *
   */
  constructor() {
    this.finalOperationOld = null;
    this.finalOperation = null;
    this.realTensor = null;
  }

  /**
   *
   * @param {ActivationEscaping.ScaleBoundsArray} scaleBoundsArray  The tensor placeholder's ScaleBoundsArray.
   */
  set_height_width_channelCount_scaleBoundsArray(
    height, width, channelCount, channelCount_lowerHalf, channelCount_higherHalf, scaleBoundsArray ) {
    this.height = height;
    this.width = width;
    this.channelCount = channelCount;
    this.channelCount_lowerHalf = channelCount_lowerHalf;
    this.channelCount_higherHalf = channelCount_higherHalf;
    this.scaleBoundsArray = scaleBoundsArray;
  }

  /**
   *
   * @param {TensorPlaceholder} aTensorPlaceholder
   *   The tensor placeholder's height, width, channelCount, scaleBoundsArray will be used directly (i.e. not cloned) by this
   * tensor placeholder. Note: The .finalOperationOld, finalOperation and .realTensor are not used.
   */
  set_height_width_channelCount_scaleBoundsArray_byTensorPlaceholder( aTensorPlaceholder ) {
    this.set_height_width_channelCount_scaleBoundsArray(
      aTensorPlaceholder.height, aTensorPlaceholder.width,
      aTensorPlaceholder.channelCount, aTensorPlaceholder.channelCount_lowerHalf, aTensorPlaceholder.channelCount_higherHalf,
      aTensorPlaceholder.scaleBoundsArray );
  }

}
<commit_msg>Update TensorPlaceholder.js<commit_after>export { Base };

/**
 * A placeholder for tensor.
 *
 *   - In Operation.TwinArray.operation_append_Xxx(), it is used for tracking a tensor's final operation which should be responsible
 *       for destroying the tensor.
 *
 *   - In operation's .apply(), it is used for transferring tensor to the next sub operation.
 *
 *
 * @member {Operation.Base} finalOperationOld
 *   The previous finalOperation. When new finalOperation is set, the finalOperationOld.setKeepInputTensor_IfNotLastOperation_Or_In()
 * usually should be called to adjust tensor destroying behavior (since it is no longer the final operation of the tensor).
 *
 * @member {Operation.Base} finalOperation
 *   The operation uses this tensor at final. It should be responsible for destroying this tensor. If null, this tensor is
 * not used by any operation.
 *
 * @member {tf.tensor} realTensor
 *   The real tensor represented by this placeholder. It is filled dynamically in an operation's apply() method.
 *
 */
class Base {

  /**
   *
   */
  constructor() {
    this.finalOperationOld = null;
    this.finalOperation = null;
    this.realTensor = null;
  }

  /**
   *
   * @param {ActivationEscaping.ScaleBoundsArray} scaleBoundsArray  The tensor placeholder's ScaleBoundsArray.
   */
  set_height_width_channelCount_scaleBoundsArray(
    height, width, channelCount, channelCount_lowerHalf, channelCount_higherHalf, scaleBoundsArray ) {
    this.height = height;
    this.width = width;
    this.channelCount = channelCount;
    this.channelCount_lowerHalf = channelCount_lowerHalf;
    this.channelCount_higherHalf = channelCount_higherHalf;
    this.scaleBoundsArray = scaleBoundsArray;
  }

  /**
   * Note: The .finalOperationOld, finalOperation and .realTensor are not modified by this method.
   *
   * @param {TensorPlaceholder} aTensorPlaceholder
   *   The tensor placeholder's height, width, channelCount, scaleBoundsArray will be used directly (i.e. not cloned) by this
   * tensor placeholder. If null, these properties will be set to null too.
   */
  set_height_width_channelCount_scaleBoundsArray_byTensorPlaceholder( aTensorPlaceholder ) {
    if ( aTensorPlaceholder ) {
      this.set_height_width_channelCount_scaleBoundsArray(
        aTensorPlaceholder.height, aTensorPlaceholder.width,
        aTensorPlaceholder.channelCount, aTensorPlaceholder.channelCount_lowerHalf, aTensorPlaceholder.channelCount_higherHalf,
        aTensorPlaceholder.scaleBoundsArray );
    } else {
      this.set_height_width_channelCount_scaleBoundsArray(
        null, null,
        null, null, null,
        null );
    }
  }

}
<|endoftext|>