In this blog post, we will understand how to perform image classification using Keras MobileNet, deploy it in Google Chrome using TensorFlow.js and use it to make live predictions in the browser.
Being a Python developer with knowledge on Web Development is surely going to help you in the field of Artificial Intelligence in the long run. Because we now have the awesome capabilities of Keras and TensorFlow in a web browser using TensorFlow.js.
The interactive demo of what we will be making at the end of the tutorial is shown below. You can play around with the buttons provided to make predictions on an image.
- Click Load Model to load MobileNet model in your browser.
- Loading image -
- Click Demo Image to import a random image that belongs to an ImageNet category.
- Click Upload Image if you want to import an image from your disk.
- Click Predict to make predictions on the image loaded in the browser.
Keras MobileNet + TensorFlow.js Demo
Note: The above demo uses state-of-the-art Keras MobileNet that's trained on ImageNet with 1000 categories. If you upload an image that doesn't belong to any of the 1000 ImageNet categories, then the prediction might not be accurate!
Basic MobileNet in Python
In Keras, MobileNet resides in the applications module. Keras offers out of the box image classification using MobileNet if the category you want to predict is available in the ImageNet categories. If the category doesn’t exist in ImageNet categories, there is a method called fine-tuning that tunes MobileNet for your dataset and classes which we will discuss in another tutorial.
MobileNet offers tons of advantages than other state-of-the-art convolutional neural networks such as VGG16, VGG19, ResNet50, InceptionV3 and Xception.
- MobileNets are light weight deep neural networks best suited for mobile and embedded vision applications.
- MobileNets are based on a streamlined architecture that uses depthwise separable convolutions.
- MobileNet uses two simple global hyperparameters that efficiently trades off between accuracy and latency.
- MobileNet could be used in object detection, finegrain classification, face recognition, large-scale geo localization etc.
Following are the advantages of using MobileNet over other state-of-the-art deep learning models.
- Reduced network size - 17MB.
- Reduced number of parameters - 4.2 million.
- Faster in performance and are useful for mobile applications.
- Small, low-latency convolutional neural network.
Advantages always come up with some disadvantages and with MobileNet, it’s the accuracy. Yes! Eventhough MobileNet has reduced size, reduced parameters and performs faster, it is less accurate than other state-of-the-art networks as discussed in this paper. But don’t worry. There is only a slight reduction in accuracy when compared to other networks.
In this tutorial, we will follow the steps shown in Figure 1 to make Keras MobileNet available in a web browser using TensorFlow.js.
First, we will write a simple python script to make predictions on a test image using Keras MobileNet.
Before sending an image into MobileNet, we need to process the image using 4 simple steps. And to do that, you don’t need OpenCV. Keras provides all the necessary functions under keras.preprocessing module, and with some basic numpy functions, you are ready to go!
- Load the image and convert it to MobileNet’s input size (224, 224) using load_img() function.
- Convert the image into a numpy array using img_to_array().
- Expand the dimensions of the numpy array using np.expand_dims().
- Preprocess the image by rescaling all the values to the range [-1, 1] using mobilenet.preprocess_input().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# organize imports
import numpy as np
from keras.models import Model
from keras.preprocessing import image
from keras.applications import imagenet_utils, mobilenet
import tensorflowjs as tfjs
# process an image to be mobilenet friendly
def process_image(img_path):
img = image.load_img(img_path, target_size=(224, 224))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
pImg = mobilenet.preprocess_input(img_array)
return pImg
# main function
if __name__ == '__main__':
# path to test image
test_img_path = "G:\\git-repos\\mobile-net-projects\\dataset\\test\\test_image_1.jpg"
# process the test image
pImg = process_image(test_img_path)
# define the mobilenet model
mobilenet = mobilenet.MobileNet()
# make predictions on test image using mobilenet
prediction = mobilenet.predict(pImg)
# obtain the top-5 predictions
results = imagenet_utils.decode_predictions(prediction)
print(results)
# convert the mobilenet model into tf.js model
save_path = "output\\mobilenet"
tfjs.converters.save_keras_model(mobilenet, save_path)
print("[INFO] saved tf.js mobilenet model to disk..")
1
2
3
4
5
[[('n01806143', 'peacock', 0.9998889),
('n01806567', 'quail', 3.463593e-05),
('n02018795', 'bustard', 2.7573227e-05),
('n01847000', 'drake', 1.1352683e-05),
('n01795545', 'black_grouse', 1.0532762e-05)]]
- Lines 2-5 imports all the necessary functions to work with.
- Lines 8-13 is the special definition we use to process an image so that it becomes MobileNet friendly.
- Line 19 defines the test image path.
- Line 22 preprocesses the test image.
- Line 25 instantiates the MobileNet model.
- Line 28 makes predictions on the test image using MobileNet model.
- Line 31 gives the top-5 predictions of the test image.
- Line 32 prints out the top-5 predictions of the test image.
- Lines 36-38 converts keras mobilenet model into tf.js layers format at save_path.
Please make sure you change the test_img_path in line 19 to test an image from your disk. Figure 2 (shown below) is the test image that I have chosen and the MobileNet model accurately predicted it as a peacock with a probability of 99.99%. Pretty cool! 😍
Cool! Everything works perfectly in our Python environment. Now, we will use this pretrained mobile net model in a web browser.
Convert Keras model into Tf.js layers format
Before deploying a keras model in web, we need to convert the Keras mobilenet python model into tf.js layers format (which we already did in lines 36-38).
To deploy a Keras model in web, we need a package called tensorflowjs. Run the below command to get it.
1
pip install tensorflowjs
After installing it, you can either run the command as a standalone one or you can integrate it in your python script as shown below (which I prefer).
1
2
3
tensorflowjs_converter --input_format keras \
path_to_keras_model.h5 \
path/to/tfjs_target_dir
1
2
3
4
5
6
7
8
import tensorflowjs as tfjs
def train(...):
model = keras.models.Sequential() # for example
...
model.compile(...)
model.fit(...)
tfjs.converters.save_keras_model(model, tfjs_target_path)
The tfjs_target_path or save_path (in our case) is a folder that contains model.json and a set of sharded weight binary files. If you take a look into model.json file, you will see the model architecture or graph (a description of layers and their connections) plus a manifest of the weight files.
Keras model into TensorFlow JS
For this tutorial, I used my GitHub pages repo to hold the keras mobilenet model files. I copied the entire folder under save_path here.
This is crucial for our application to work because if you host these model files in a different server, you might face CORS issue in your web app. Storing your model files in the same domain as your web app is safer and preferred way.
Let’s get started with the sweet TensorFlow.js 😘
You need these three javascript libraries loaded in your website.
- IMAGENET_CLASSES variable that has all the ImageNet categories indexed which could easily be loaded from here.
- TensorFlow.js latest source.
- jQuery to make JavaScript easier.
1
2
3
<script type="text/javascript" src="/js/imagenet_classes.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
Once you load all the above three scripts, you can open up a new file named mobile-net.js that will have all the functionality needed to make Keras MobileNet model work in a web browser.
The user interface that I made at the start of the tutorial has HTML, CSS and JavaScript code combined. We will look into model specific part instead of looking into every single line of code.
1. Load Keras model into TF.js
Firstly, you need to load the Keras pretrained model json that you have stored in your web server. To do this, you can use the below code snippet.
The below code snippet is an async function that loads a keras model json using tf.loadModel(). In line 17, await means without disturbing the UI, you are asking JavaScript to load model behind the scenes. To view the status of model loading, we use a progress bar as well as console.log().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let model;
async function loadModel() {
console.log("model loading..");
// display model loading progress box
loader = document.getElementById("progress-box");
load_button = document.getElementById("load-button");
loader.style.display = "block";
// model name is "mobilenet"
modelName = "mobilenet";
// clear the model variable
model = undefined;
// load the model using a HTTPS request (where you have stored your model files)
model = await tf.loadLayersModel('https://gogul09.github.io/models/mobilenet/model.json');
// hide model loading progress box
loader.style.display = "none";
load_button.disabled = true;
load_button.innerHTML = "Loaded Model";
console.log("model loaded..");
}
2. Upload image from disk
To upload an image from disk, you can use the below code snippet which makes use of HTML5 File API. I have used a button Upload Image which has a change handler associated with it.
1
2
<!-- used to get image from disk -->
<input id="select-file-image" type="file">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// if there is a change to "Upload Image" button,
// load and render the image
$("#select-file-image").change(function() {
renderImage(this.files[0]);
}
// renders the image which is loaded from disk to the img tag
function renderImage(file) {
var reader = new FileReader();
reader.onload = function(event) {
img_url = event.target.result;
document.getElementById("test-image").src = img_url;
}
reader.readAsDataURL(file);
}
3. Predict using MobileNet model
To make predictions using mobilenet that’s now loaded into Tf.js environment, we need to perform two steps.
- Preprocess the input image to be mobilenet friendly.
- Make predicitons on the input image.
3.1 Preprocess the input image
As I have already mentioned, input image size to mobilenet is [224, 224] as well as the features are scaled between [-1, 1]. You need to perform these two steps before making predictions using the model. To do this, we use preprocessImage() function that takes in two arguments image and modelName.
The input image can easily be loaded using tf.fromPixels() , resized using resizeNearestNeighbor() and converting all the values in the image to float using toFloat().
After that, we feature scale the values in the image tensor using a scalar value of 127.5 which is the center value of image pixel range [0, 255]. For each pixel value in the image, we subtract this offset value and divide by this offset value to scale between [-1, 1]. We then expand the dimensions using expandDims().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// preprocess the image to be mobilenet friendly
function preprocessImage(image, modelName) {
// resize the input image to mobilenet's target size of (224, 224)
let tensor = tf.browser.fromPixels(image)
.resizeNearestNeighbor([224, 224])
.toFloat();
// if model is not available, send the tensor with expanded dimensions
if (modelName === undefined) {
return tensor.expandDims();
}
// if model is mobilenet, feature scale tensor image to range [-1, 1]
else if (modelName === "mobilenet") {
let offset = tf.scalar(127.5);
return tensor.sub(offset)
.div(offset)
.expandDims();
}
// else throw an error
else {
alert("Unknown model name..")
}
}
3.2 Predict using Tf.js model
After preprocessing the image, I have made a handler for Predict button. Again, this is also an async function that uses await till the model make successfull predictions.
Prediction using a Tf.js model is straightforward as Keras which uses model.predict(tensor). To get the predictions, we pass it data() to the former.
Results from the predictions are mapped to an array named results using IMAGENET_CLASSES that we loaded at the beginning of this tutorial. We also sort this array based on the probability that is highest using sort() and take only the top-5 probabilities using slice().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// If "Predict Button" is clicked, preprocess the image and
// make predictions using mobilenet
$("#predict-button").click(async function () {
// check if model loaded
if (model == undefined) {
alert("Please load the model first..")
}
// check if image loaded
if (document.getElementById("predict-box").style.display == "none") {
alert("Please load an image using 'Demo Image' or 'Upload Image' button..")
}
// html-image element can be given to tf.fromPixels
let image = document.getElementById("test-image");
let tensor = preprocessImage(image, modelName);
// make predictions on the preprocessed image tensor
let predictions = await model.predict(tensor).data();
// get the model's prediction results
let results = Array.from(predictions)
.map(function (p, i) {
return {
probability: p,
className: IMAGENET_CLASSES[i]
};
}).sort(function (a, b) {
return b.probability - a.probability;
}).slice(0, 5);
// display the top-1 prediction of the model
document.getElementById("results-box").style.display = "block";
document.getElementById("prediction").innerHTML = "MobileNet prediction - <b>" + results[0].className + "</b>";
// display top-5 predictions of the model
var ul = document.getElementById("predict-list");
ul.innerHTML = "";
results.forEach(function (p) {
console.log(p.className + " " + p.probability.toFixed(6));
var li = document.createElement("LI");
li.innerHTML = p.className + " " + p.probability.toFixed(6);
ul.appendChild(li);
});
});
There you go! We now have the power of state-of-the-art Keras pretrained model MobileNet in a client browser that is able to make predictions on images that belong to ImageNet category.
Notice that the mobilenet model loads very quickly in the browser and makes predictions very fast 😎
References
- TensorFlow.js - Official Documentation
- Keras - Official Documentation
- Importing a Keras model into TensorFlow.js
- Introduction to TensorFlow.js - Intelligence and Learning
- TensorFlow.js: Tensors - Intelligence and Learning
- TensorFlow.js Quick Start
- Session 6 - TensorFlow.js - Intelligence and Learning
- Session 7 - TensorFlow.js Color Classifier - Intelligence and Learning
- Tensorflow.js Explained
- Webcam Tracking with Tensorflow.js
- Try TensorFlow.js in your browser
In case if you found something useful to add to this article or you found a bug in the code or would like to improve some points mentioned, feel free to write it down in the comments. Hope you found something useful here.


Planet Protector: [ MAIN EXPERIENCE ]
Actual MIT Reality Hack (2020) submission, with follow-up edits. Currently has a loading bug, assets might take too long to load.
Planet Protector Arcade: [ GAMEPLAY ]
Arcade mode was a proof of concept for getting the scoreboard logic working... but happens to be pretty cool on its own.


About Me
My name is Maritza Medina I am 18 years old!
I am currently attending the Year Up program to be a softwear testing engineer. I am also attending college classes at south seattle college as part of the program. I recently graduated highschool june 2020 and right after graduating I applied for the Year Up program, since aroung age 12 I knew the computer feild is what I wanted to pressue and the Year Up program has been a amazing way to reach this so far.
Some of the things I enjoy doing on my free time is painting, yoga, ceramics, making jewerly, building etc. I enjoy doing a lot of hands on activties and overall staying creative!
My future goals
In the future I hope to be working at Microsoft as a tester because that has always been my dream jobs I feel that my traits would allow me to thrive as a tester. I hope to be financially stable as well as have a bit of extra money to help my family as well as buy propertys and learn how to invest my money. More than anything my main goal for the future is to be happy and live my life without regrets being happy and sucessful.


Roriz Social Sanitary Facilities / pema studio
- Curated by Matheus Pereira
- about 21 hours
Public Architecture · Roriz, Portugal
- version="1.0" encoding="UTF-8"? Architects: pema studio
- AreaArea of this architecture projectArea: 43.0 ft2
- version="1.0" encoding="UTF-8"?YearCompletion year of this architecture project Year: 2018
- version="1.0" encoding="UTF-8"?PhotographsPhotographs: pema studio
- version="1.0" encoding="UTF-8"?ManufacturersBrands with products used in this architecture project Manufacturers: CIN, Cinca, Granifofo, Grohe
Text description provided by the architects. The study focused on public use sanitary facilities, in need of urgent intervention. A previously degraded and dysfunctional space whose requalification is based on three fundamental principles: the space functionality, the limit budget imposed and respect for the context, spirit and history of this place.
The project entire development came from a clear functional problem, the access to a storage room, made through the entrance into the men's toilets.
In response to this problem, the project was developed around the creation of a single entrance into the building, which assumes itself as an extension of the public road to its interior and gives direct access to the storage room, it's through this new "inner street" that the access to the men's and women's toilets is made.
The choice for the stabilized oxidized iron grid arises from the historical context of this old building, an old chain of this region of which still remains the heavily oxidized grid in the small windows.
Added to this all, is the will to do something contemporary, provocative and relaxed that can challenge the typical local public work paradigm.
The monolithic granite washbasin, an abundant stone in this region, assumes an imposing form and translates the craftsmanship of working on stone, an art once common in the people of this place, currently in extinction.


|
KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
|
MVQN acceleration scheme MultiVectorQuasiNewton convergence accelerator from Bogaers et al. 2016. More...
#include <mvqn_convergence_accelerator.hpp>
Public Member Functions | |
Life Cycle | |
| MVQNFullJacobianConvergenceAccelerator ()=default | |
| Construct a new MVQNFullJacobianConvergenceAccelerator object Default constructor of MVQNFullJacobianConvergenceAccelerator. More... | |
| MVQNFullJacobianConvergenceAccelerator (Parameters rConvAcceleratorParameters) | |
| Construct a new MVQNFullJacobianConvergenceAccelerator object MultiVector Quasi-Newton convergence accelerator with full Jacobian json settings constructor This constructor also makes possible the MVQN usage for the interface block Newton equations. More... | |
| MVQNFullJacobianConvergenceAccelerator (const double AbsCutOff) | |
| Construct a new MVQNFullJacobianConvergenceAccelerator object This constructor intended to be used with the interface block Newton equations (. More... | |
| MVQNFullJacobianConvergenceAccelerator (const MVQNFullJacobianConvergenceAccelerator &rOther) | |
| virtual | ~MVQNFullJacobianConvergenceAccelerator () |
Operations | |
| void | InitializeSolutionStep () override |
| Initialize the internal iteration counter This method initializes the convergence acceleratior iteration counter at the begining of the step. More... | |
| void | UpdateSolution (const VectorType &rResidualVector, VectorType &rIterationGuess) override |
| Performs the solution update This method computes the solution update using a Jacobian approximation. Such Jacobian approximation is computed with the MVQN (MultiVector Quasi-Newton method) algorithm. More... | |
| void | FinalizeNonLinearIteration () override |
| Do the MVQN variables update Updates the MVQN iteration variables for the next non-linear iteration. More... | |
| void | FinalizeSolutionStep () override |
| Save the current step Jacobian This method saves the current step Jacobian as previous step Jacobian for the next time step iteration. More... | |
| virtual Parameters | GetDefaultParameters () const |
| Public Member Functions inherited from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace > | |
| ConvergenceAccelerator ()=default | |
| ConvergenceAccelerator (Parameters ThisParameters) | |
| ConvergenceAccelerator (const ConvergenceAccelerator &Other)=delete | |
| virtual | ~ConvergenceAccelerator ()=default |
| virtual void | Initialize () |
| Initialize the convergence accelerator Operations that are required to be done once before the resolution of the problem. More... | |
| virtual void | InitializeNonLinearIteration () |
| Operations before each non-linear iteration Performs all the required operations that should be done before each non-linear iteration. More... | |
| virtual void | Finalize () |
| Finalize the convergence accelerator Perform all the operations required after the resolution of the problem. More... | |
| virtual void | Clear () |
| Clear the internal storage Clears all the internal data (e.g. previous observation matrices) More... | |
| virtual void | SetEchoLevel (int Level) |
| Set the Echo Level object Set the echo level of the convergence accelerator. More... | |
| int | GetEchoLevel () |
| Get the Echo Level object Get the echo level of the convergence accelerator. More... | |
| virtual bool | IsBlockNewton () const |
| Checks if the update direction is unique or double For the current convergence accelerator, this method returns information about the nature of the coupling If it is block Newton, the update is done in both directions. Otherwise, it is done in one direction. More... | |
| KRATOS_CLASS_POINTER_DEFINITION (ConvergenceAccelerator) | |
Protected Member Functions | |
Protected Operations | |
| virtual void | UpdateInverseJacobianApproximation (const VectorType &rResidualVector, const VectorType &rIterationGuess) |
| Update the inverse Jacobian approximation This method first appends the current iteration values to the observation matrix to then update the inverse Jacobian approximation. More... | |
| void | UpdateIterationGuess (VectorType &rIterationGuess) |
| Calculate the current iteration correction This method calculates the current iteration correction and applies it to the provided current iteration guess. More... | |
| void | AppendCurrentIterationInformation (const VectorType &rResidualVector, const VectorType &rIterationGuess) |
| Append the current iteration information to the observation matrices This method appends the current iteration information to the observation matrices First of all appends the provided information to then check the singularity of the new data If the new columns are linear dependent to the existent ones, the new info is dropped Nothing is appent in the first 0 iteration since the observation matrices collect the increments between iterations. More... | |
| void | StoreDataColumns () |
| Store the current iterations data columns This method initializes the observation matrices for the current iteration and updates their value If the number of iterations becomes larger thant the interface DOFs the oldest data is drop to prevent singularity. More... | |
| void | CheckCurrentIterationInformationSingularity () |
| Check the new data singularity This method checks that the new observation data is not linearly dependent to the existent one To do that the ratio between the minimum and maximum eigenvalues is calculated with a small SVD The matrices of the SVD are also employed to calculate the Moore-Penrose pseudoinverse (trans(V)*V)^-1. More... | |
| void | CalculateInverseJacobianApproximation () |
| Calculates the inverse Jacobian approximation This method calculates the MVQN inverse Jacobian approximation If not initialized yet, the current and previous step Jacobians are initialized as required. More... | |
| virtual void | CalculateCorrectionWithJacobian (VectorType &rCorrection) |
| Calculates the current iteration correction with the Jacobian This method calculates the current iteration correction with the inverse Jacobian approximation. More... | |
| virtual void | UpdateCurrentJacobianMatrix () |
| Updates the inverse Jacobian approximation This method updates the inverse Jacobian approximation with the current iteration information. More... | |
Protected Access | |
| std::size_t | GetProblemSize () const override |
| Get the Problem Size object This method returns the problem size, which equals the number of interface DOFs. More... | |
| std::size_t | GetConvergenceAcceleratorIteration () const |
| std::size_t | GetNumberOfObservations () const |
| bool | IsFirstCorrectionPerformed () const |
| bool | IsUsedInBlockNewtonEquations () const |
| Returns the a bool indicating if IBQN are used This method returns a bool flag indicating if the current MVQN instance is to be used in the IBQN equations. More... | |
| VectorPointerType | pGetCurrentIterationResidualVector () |
| Get the residual vector This method returns a pointer to the current iteration residual vector. More... | |
| MatrixPointerType | pGetInverseJacobianApproximation () override |
| Get the inverse Jacobian approximation This method returns a pointer to the current inverse Jacobian approximation matrix. More... | |
| MatrixPointerType | pGetResidualObservationMatrix () |
| Get the observation matrix V This method returns a pointer to the residual observation matrix. More... | |
| MatrixPointerType | pGetSolutionObservationMatrix () |
| Get the observation matrix W This method returns a pointer to the solution observation matrix. More... | |
| void | SetInitialRelaxationOmega (const double Omega) |
| Set the Initial Relaxation Omega This method sets the relaxation parameter to be used in the very first correction. More... | |
| void | SetCutOffTolerance (const double CutOffTolerance) |
| Set the Cut Off Tolerance This method sets the cut off relative tolerance value to be used in the information singularity check. More... | |
| virtual MatrixPointerType | pGetJacobianDecompositionMatrixQU () |
| virtual MatrixPointerType | pGetJacobianDecompositionMatrixSigmaV () |
| virtual MatrixPointerType | pGetOldJacobianDecompositionMatrixQU () |
| virtual MatrixPointerType | pGetOldJacobianDecompositionMatrixSigmaV () |
| Protected Member Functions inherited from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace > | |
| virtual void | ComputeJacobianApproximation () |
Friends | |
Friends | |
| class | IBQNMVQNConvergenceAccelerator< TSparseSpace, TDenseSpace > |
| class | IBQNMVQNRandomizedSVDConvergenceAccelerator< TSparseSpace, TDenseSpace > |
Type Definitions | |
| typedef ConvergenceAccelerator< TSparseSpace, TDenseSpace > | BaseType |
| typedef BaseType::Pointer | BaseTypePointer |
| typedef BaseType::DenseVectorType | VectorType |
| typedef BaseType::DenseVectorPointerType | VectorPointerType |
| typedef BaseType::DenseMatrixType | MatrixType |
| typedef BaseType::DenseMatrixPointerType | MatrixPointerType |
| KRATOS_CLASS_POINTER_DEFINITION (MVQNFullJacobianConvergenceAccelerator) | |
Additional Inherited Members | |
| Public Types inherited from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace > | |
| typedef TSparseSpace::VectorType | VectorType |
| typedef TSparseSpace::MatrixType | MatrixType |
| typedef TSparseSpace::VectorPointerType | VectorPointerType |
| typedef TSparseSpace::MatrixPointerType | MatrixPointerType |
| typedef TDenseSpace::VectorType | DenseVectorType |
| typedef TDenseSpace::MatrixType | DenseMatrixType |
| typedef TDenseSpace::MatrixPointerType | DenseMatrixPointerType |
| typedef TDenseSpace::VectorPointerType | DenseVectorPointerType |
| Protected Attributes inherited from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace > | |
| int | mEchoLevel |
MVQN acceleration scheme MultiVectorQuasiNewton convergence accelerator from Bogaers et al. 2016.
Forward declaration of standard MVQN This is required since the include ward avoids the inclusion of the standard MVQN
| TSparseSpace | Linear algebra sparse space |
| TDenseSpace | Linear algebra dense space |
| typedef ConvergenceAccelerator<TSparseSpace, TDenseSpace> Kratos::MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace >::BaseType |
| typedef BaseType::Pointer Kratos::MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace >::BaseTypePointer |
| typedef BaseType::DenseMatrixPointerType Kratos::MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace >::MatrixPointerType |
| typedef BaseType::DenseMatrixType Kratos::MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace >::MatrixType |
| typedef BaseType::DenseVectorPointerType Kratos::MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace >::VectorPointerType |
| typedef BaseType::DenseVectorType Kratos::MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace >::VectorType |
|
explicitdefault |
Construct a new MVQNFullJacobianConvergenceAccelerator object Default constructor of MVQNFullJacobianConvergenceAccelerator.
|
inlineexplicit |
Construct a new MVQNFullJacobianConvergenceAccelerator object MultiVector Quasi-Newton convergence accelerator with full Jacobian json settings constructor This constructor also makes possible the MVQN usage for the interface block Newton equations.
| rConvAcceleratorParameters | Json string encapsulating the settings |
|
inlineexplicit |
Construct a new MVQNFullJacobianConvergenceAccelerator object This constructor intended to be used with the interface block Newton equations (.
| AbsCutOff | absolute tolerance for the observation cut off |
| Kratos::MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace >::MVQNFullJacobianConvergenceAccelerator | ( | const MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace > & | rOther | ) |
Copy Constructor.
|
inlinevirtual |
Destructor.
|
inlineprotected |
Append the current iteration information to the observation matrices This method appends the current iteration information to the observation matrices First of all appends the provided information to then check the singularity of the new data If the new columns are linear dependent to the existent ones, the new info is dropped Nothing is appent in the first 0 iteration since the observation matrices collect the increments between iterations.
| rResidualVector | Current iteration residual vector (\tilde{u}_{k} - u_{k}) |
| rIterationGuess | Current iteration initial guess (previous iteration corrected value u_{k}) |
|
inlineprotectedvirtual |
Calculates the current iteration correction with the Jacobian This method calculates the current iteration correction with the inverse Jacobian approximation.
| rCorrection | Auxiliary vector to store the correction |
Reimplemented in Kratos::MVQNRandomizedSVDConvergenceAccelerator< TSparseSpace, TDenseSpace >.
|
inlineprotected |
Calculates the inverse Jacobian approximation This method calculates the MVQN inverse Jacobian approximation If not initialized yet, the current and previous step Jacobians are initialized as required.
|
inlineprotected |
Check the new data singularity This method checks that the new observation data is not linearly dependent to the existent one To do that the ratio between the minimum and maximum eigenvalues is calculated with a small SVD The matrices of the SVD are also employed to calculate the Moore-Penrose pseudoinverse (trans(V)*V)^-1.
|
inlineoverridevirtual |
Do the MVQN variables update Updates the MVQN iteration variables for the next non-linear iteration.
Reimplemented from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace >.
|
inlineoverridevirtual |
Save the current step Jacobian This method saves the current step Jacobian as previous step Jacobian for the next time step iteration.
Reimplemented from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace >.
Reimplemented in Kratos::MVQNRandomizedSVDConvergenceAccelerator< TSparseSpace, TDenseSpace >.
|
inlineprotected |
|
inlinevirtual |
|
inlineprotected |
|
inlineoverrideprotectedvirtual |
Get the Problem Size object This method returns the problem size, which equals the number of interface DOFs.
Reimplemented from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace >.
|
inlineoverridevirtual |
Initialize the internal iteration counter This method initializes the convergence acceleratior iteration counter at the begining of the step.
Reimplemented from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace >.
|
inlineprotected |
|
inlineprotected |
Returns the a bool indicating if IBQN are used This method returns a bool flag indicating if the current MVQN instance is to be used in the IBQN equations.
| Kratos::MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace >::KRATOS_CLASS_POINTER_DEFINITION | ( | MVQNFullJacobianConvergenceAccelerator< TSparseSpace, TDenseSpace > | ) |
|
inlineprotected |
Get the residual vector This method returns a pointer to the current iteration residual vector.
|
inlineoverrideprotectedvirtual |
Get the inverse Jacobian approximation This method returns a pointer to the current inverse Jacobian approximation matrix.
Reimplemented from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace >.
|
inlineprotectedvirtual |
|
inlineprotectedvirtual |
|
inlineprotectedvirtual |
|
inlineprotectedvirtual |
|
inlineprotected |
Get the observation matrix V This method returns a pointer to the residual observation matrix.
|
inlineprotected |
Get the observation matrix W This method returns a pointer to the solution observation matrix.
|
inlineprotected |
Set the Cut Off Tolerance This method sets the cut off relative tolerance value to be used in the information singularity check.
| CutOffTolerance | Cut off relative tolerance to be set |
|
inlineprotected |
Set the Initial Relaxation Omega This method sets the relaxation parameter to be used in the very first correction.
| Omega | Relaxation parameter to be set |
|
inlineprotected |
Store the current iterations data columns This method initializes the observation matrices for the current iteration and updates their value If the number of iterations becomes larger thant the interface DOFs the oldest data is drop to prevent singularity.
|
inlineprotectedvirtual |
Updates the inverse Jacobian approximation This method updates the inverse Jacobian approximation with the current iteration information.
|
inlineprotectedvirtual |
Update the inverse Jacobian approximation This method first appends the current iteration values to the observation matrix to then update the inverse Jacobian approximation.
| rResidualVector | Current iteration residual vector (\tilde{u}_{k} - u_{k}) |
| rIterationGuess | Current iteration initial guess (previous iteration corrected value u_{k}) |
Reimplemented in Kratos::MVQNRandomizedSVDConvergenceAccelerator< TSparseSpace, TDenseSpace >.
|
inlineprotected |
Calculate the current iteration correction This method calculates the current iteration correction and applies it to the provided current iteration guess.
| rIterationGuess | Current iteration initial guess to be corrected (previous iteration corrected value u_{k}) |
|
inlineoverridevirtual |
Performs the solution update This method computes the solution update using a Jacobian approximation. Such Jacobian approximation is computed with the MVQN (MultiVector Quasi-Newton method) algorithm.
| rResidualVector | Residual vector from the residual evaluation |
| rIterationGuess | Current iteration guess to be corrected. Should be initialized to zero outside the convergence accelerator. |
Reimplemented from Kratos::ConvergenceAccelerator< TSparseSpace, TDenseSpace >.
|
friend |
|
friend |


Chemtrails refers to the theory that governments or other parties are engaged in a secret program to add toxic chemicals to the atmosphere from aircraft in a way that forms visible plumes in the sky, somewhat similar to contrails. Various different motivations for this alleged spraying are speculated, including sterilization, reduction of life expectancy, mind control or weather control.
In the late 1990s, many people became alarmed by what they believed were new kinds of contrails, dubbed chemtrails, that were being used to change the Earth's atmosphere. What likely kicked off this sudden chemtrail craze was a paper published by the Air Force in 1996, "Weather as a Force Multiplier," where a group of military researchers speculated about how they could use weather manipulation as a form of combat.


AWS has very good support for metrics, and a very powerful way of implementing these metrics with other functionality. The problem is that if you work on a hobby project it's quite expensive to pay 0.3$ per metric. That is why this library instead helps you to read and write metrics to S3, so that you can track developments over time without accumulating a high running cost.
For full information, please refer to the API documentation to see available classes and their functions.
npx
https://github.com/npm/npx. This allows invoking of the other global npm requirements in the repository (Typescript, Jest) without having to install them.Not available yet.
Contributions, if they are in line with expanding functionality that can help with layout logic are welcome. Requirements for pull requests are:
Generated using TypeDoc


Support stats
More...
|
| long | Resurrects [get, set] |
| | Number of time ressurected someone More...
|
| |
| double | ResurrectTime [get, set] |
| | Time passed on ressurecting More...
|
| |
| long | CondiCleanse [get, set] |
| | Number of time a condition was removed, self excluded More...
|
| |
| double | CondiCleanseTime [get, set] |
| | Total time of condition removed, self excluded More...
|
| |
| long | CondiCleanseSelf [get, set] |
| | Number of time a condition was removed from self More...
|
| |
| double | CondiCleanseTimeSelf [get, set] |
| | Total time of condition removed from self More...
|
| |
| long | BoonStrips [get, set] |
| | Number of time a boon was removed More...
|
| |
| double | BoonStripsTime [get, set] |
| | Total time of boons removed from self More...
|
| |
◆ BoonStrips
| long GW2EIBuilders.JsonModels.JsonStatistics.JsonPlayerSupport.BoonStrips |
|
getset |
Number of time a boon was removed
◆ BoonStripsTime
| double GW2EIBuilders.JsonModels.JsonStatistics.JsonPlayerSupport.BoonStripsTime |
|
getset |
Total time of boons removed from self
◆ CondiCleanse
| long GW2EIBuilders.JsonModels.JsonStatistics.JsonPlayerSupport.CondiCleanse |
|
getset |
Number of time a condition was removed, self excluded
◆ CondiCleanseSelf
| long GW2EIBuilders.JsonModels.JsonStatistics.JsonPlayerSupport.CondiCleanseSelf |
|
getset |
Number of time a condition was removed from self
◆ CondiCleanseTime
| double GW2EIBuilders.JsonModels.JsonStatistics.JsonPlayerSupport.CondiCleanseTime |
|
getset |
Total time of condition removed, self excluded
◆ CondiCleanseTimeSelf
| double GW2EIBuilders.JsonModels.JsonStatistics.JsonPlayerSupport.CondiCleanseTimeSelf |
|
getset |
Total time of condition removed from self
◆ Resurrects
| long GW2EIBuilders.JsonModels.JsonStatistics.JsonPlayerSupport.Resurrects |
|
getset |
Number of time ressurected someone
◆ ResurrectTime
| double GW2EIBuilders.JsonModels.JsonStatistics.JsonPlayerSupport.ResurrectTime |
|
getset |
Time passed on ressurecting
The documentation for this class was generated from the following file:


Class HandControllerPoseProfile
A hand controller pose definition with recorded hand joint data. Defined hand poses can be recognized and trigger input actions.
Inherited Members
Namespace: XRTK.Definitions.Controllers.Hands
Assembly: XRTK.dll
Syntax
[CreateAssetMenu(menuName = "Mixed Reality Toolkit/Input System/Hand Controller Pose", fileName = "HandControllerPose", order = 2)]
public class HandControllerPoseProfile : BaseMixedRealityProfile
Properties
| Improve this Doc View SourceData
Gets the gesture definition's joint information used to simulate the gesture.
Declaration
public TextAsset Data { get; }
Property Value
| Type | Description |
|---|---|
| TextAsset |
Description
Describes the hand pose.
Declaration
public string Description { get; }
Property Value
| Type | Description |
|---|---|
| String |
DidBake
Was the data for this pose definition baked?
Declaration
public bool DidBake { get; }
Property Value
| Type | Description |
|---|---|
| Boolean |
FingerCurlStrengths
Finger curling values per hand finger.
Declaration
public float[] FingerCurlStrengths { get; }
Property Value
| Type | Description |
|---|---|
| Single[] |
GripStrength
What's the grip strength of the hand?
Declaration
public float GripStrength { get; }
Property Value
| Type | Description |
|---|---|
| Single |
Id
A unique ID to the pose.
Declaration
public string Id { get; }
Property Value
| Type | Description |
|---|---|
| String |
IsDefault
Is this the default (idle) hand pose?
Declaration
public bool IsDefault { get; }
Property Value
| Type | Description |
|---|---|
| Boolean |
IsGripping
Is the hand currently in a gripping pose?
Declaration
public bool IsGripping { get; }
Property Value
| Type | Description |
|---|---|
| Boolean |
KeyCode
Gets the key code used to trigger this gesture simulation.
Declaration
public KeyCode KeyCode { get; }
Property Value
| Type | Description |
|---|---|
| KeyCode |


---
layout: post
title: Tivo To Go.. Finally!
categories: []
tags: []
status: publish
type: post
published: true
meta:
_original_post_id: ''
_original_import_author: John Duprey
author:
---
The
TivoToGo software update finally made it to my Tivo! This means that I can download recorded shows from Tivo and watch them on a Windows computer. Well.. I use a Mac so I'm using my wife's computer to download shows. The download is kinda slow. The files are huge and from what I've read, Tivo isn't able to take advantage of my 100 Mbps connection. :(
While I patiently wait for Mac software, I'm taking advantage of the web API's. Thanks to the guys who
threw together these PHP scripts, you can see what's on my Tivo. :) Marvel at our awesome taste in programming:
Duprey's Tivo [
RSS]
Tivo has
apparently partnered with Sonic to produce DVD burning software (Windows) for the Tivo videos. However, my hope is that I will be able to one day download the shows to my Mac and burn DVDs for personal use. There's already a
hack to transform the digital rights managed (DRM) tivo video to standard MPEG2 (DVD format) for Windows.


This is the simplest custom view that you can get.
Note that libraries like Bootstrap, jQuery and Chosen are included by default as the admin uses them internally.
The admin's custom views follow the Modular web applications with Node.js and Express approach presented by TJ Holowaychuk.
The only difference here is that we're dealing with mustache
templates.


Back to all open positions
Senior Product Owner
The Product Owner takes market requirements and translates them into detailed technical user stories which the engineering teams can implement effectively. You will be working with external and internal stakeholders to perform market analysis and customer needs analysis to ensure features being implemented have a world class user experience. In addition, you'll be a master of definition and work prioritization with development scrum teams to ensure new features are delivered on time and in scope.
Responsibilities
- The Product Owner takes market requirements and translates them into detailed technical user stories which the engineering teams can implement effectively.
- Work with external and internal stakeholders to perform market analysis and customer needs analysis to ensure features being implemented have a world class user experience.
- Definition and work prioritization with development scrum teams to ensure new features are delivered on time and in scope.
- Collaborate and interface with product management and engineering teams across BlackBerry to ensure new features and products are aligned with company direction and are positioned to deliver significant customer value.
Qualifications
- Degree in Computer Science, or equivalent technical degree or diploma program.
- Deep understanding of current cybersecurity industry and solutions, including threat assessment, prevention and remediation.
- Minimum 8 years of experience in a technical product owner role.
- Ability to translate business objectives into technical product requirements and user stories for engineering teams.
- Experience as a Product Owner in an Agile work environment..
- Demonstrated team player and strong leadership skills.
- Excellent communication skills (both written and verbal / presentation) for a variety of audiences (technical and non-technical) including senior leadership (C-Level).
- Comfortable engaging with marketing, product management, technical teams, and customer-facing activities.


EBD - Easton Bible DIctionary
Taberah
TABERAH
"TABERAH "burning, a place in the wilderness of Paran, where the “fire of the Lord” consumed the murmuring Israelites (
Numbers 11:3
;
Deuteronomy 9:22
). It was also called Kibroth-hattaavah (q.v.).
"TABERAH "burning, a place in the wilderness of Paran, where the “fire of the Lord” consumed the murmuring Israelites (Numbers 11:3; Deuteronomy 9:22). It was also called Kibroth-hattaavah (q.v.).


{% extends "./base.html" %} {% block content %} {% include "./components/navbar.html" %}
Create an account to access the best social network in the world.


Patrick Beverley had an all-time flop in Clippers’ memorable win
by Justin TerranovaThe Clippers’ 107-104 overtime victory over the Celtics will be remembered as the first game Kawhi Leonard and Paul George played together for Los Angeles. This Patrick Beverley flop, though, will be a close second.
The Clippers guard is known as one of the more ferocious defenders in the NBA (sorry, Russell Westbrook), but this will not go on his highlight reel. Beverley was guarding Jayson Tatum and crashes to the floor after Tatum grazes his face.
The slo-mo ESPN replay clearly shows the hit was not as bad as Beverley acted.
“Just watch Patrick Beverley’s reaction,” a laughing Doris Burke says as the replay airs.


To create a new admin, please fill out the information below. Once created, the new admin can log in and change their password if they desire. Deleting an admin is final. You will not be able to recover a delete admin account.


For the most part, accumulo is ready to go out of the box. To start it, first you must distribute and install
the accumulo software to each machine in the cloud that you wish to run on. The software should be installed
in the same directory on each machine and configured identically (or at least similarly... see the configuration
sections for more details). Select one machine to be your bootstrap machine, the one that you will start accumulo
with. Note that you must have passphrase-less ssh access to each machine from your bootstrap machine. On this machine,
create a conf/masters and conf/slaves file. In the masters file, type the hostname of the machine you wish to run the master on (probably localhost).
In the slaves file, type the hostnames, separated by newlines of each machine you wish to participate in accumulo as a tablet server. If you neglect
to create these files, the startup scripts will assume you are trying to run on localhost only, and will instantiate a single-node instance only.
It is probably a good idea to back up these files, or distribute them to the other nodes as well, so that you can easily boot up accumulo
from another machine, if necessary. You can also make create a conf/accumulo-env.sh
file if you want to configure any custom environment variables.
Once properly configured, you can initialize or prepare an instance of accumulo by running: bin/accumulo init
Follow the prompts and you are ready to go. This step only prepares accumulo to run, it does not start up accumulo.
Once you have configured accumulo to your liking, and distributed the appropriate configuration to each machine, you can start accumulo with bin/start-all.sh. If at any time, you wish to bring accumulo servers online after one or more have been shutdown, you can run bin/start-all.sh again. This step will only start services that are not already running. Be aware that if you run this command on more than one machine, you may unintentionally start an extra copy of the garbage collector service and the monitoring service, since each of these will run on the server on which you run this script.
Similar to the start-all.sh script, we provide a bin/stop-all.sh script to shut down accumulo. This will prompt for the root password so that it can ask the master to shut down the tablet servers gracefully. If the tablet servers do not respond, or the master takes too long, you can force a shutdown by hitting Ctrl-C at the password prompt, and waiting 15 seconds for the script to force a shutdown. Normally, once the shutdown happens gracefully, unresponsive tablet servers are forcibly shut down after 5 seconds.
Accumulo configuration information is stored in a xml file and ZooKeeper. System wide configuration information is stored in accumulo-site.xml. In order for accumulo to find this file its directory must be on the classpath. Accumulo will log a warning if it can not find it, and will use built-in default values. The accumulo scripts try to put the config directory on the classpath.
Starting with version 1.0, per-table configuration was introduced. This information is stored in ZooKeeper. This information can be manipulated using the config command in the accumulo shell. ZooKeeper will notify all tablet servers when config properties are modified. This makes it possible to change major compaction settings, for example, for a table while accumulo is running.
Per-table configuration settings override system settings.
See the possible configuration options and their default values here
It is very important how disk and memory usage are allocated across the cluster and how servers processes are allocated across the cluster.
There are a few settings that determine how much memory accumulo tablet servers use. In accumulo-env.sh there is a setting called ACCUMULO_TSERVER_OPTS. By default this is set to something like "-Xmx512m -Xms512m". These are Java jvm options asking Java to use 512 megabytes of memory. By default accumulo stores data written to it outside of the Java memory space in order to avoid pauses caused by the Java garbage collector. The amount of memory it uses for this data is determined by the accumulo setting "tserver.memory.maps.max". Since this memory is outside of the Java managed memory, the process can grow larger than the -Xmx setting. So if -Xmx is set to 512M and tserver.memory.maps.max is set to 1G, a tablet server process can be expected to use 1.5G. If tserver.memory.maps.native.enabled is set to false, then accumulo will only use memory managed by Java and the process will not use more than what -Xmx is set to. In this case the tserver.memory.maps.max setting should be 75% of the -Xmx setting.


|
BL3 SDK
0.0.1
Borderlands 3 Class Documentation
|
#include <BL3_Engine_classes.hpp>
Static Public Member Functions | |
| static UClass * | StaticClass () |
| Static Public Member Functions inherited from UObject | |
| static FChunkedFixedUObjectArray & | GetGlobalObjects () |
| template<typename T > | |
| static T * | FindObject (const std::string &name) |
| static UClass * | FindClass (const std::string &name) |
| template<typename T > | |
| static T * | GetObjectCasted (std::size_t index) |
| static UClass * | StaticClass () |
Public Attributes | |
| unsigned char | UnknownData00 [0x8] |
| EFontCacheType | FontCacheType |
| unsigned char | UnknownData01 [0x7] |
| TArray< struct FFontCharacter > | Characters |
| TArray< class UTexture2D * > | Textures |
| int | IsRemapped |
| float | EmScale |
| float | Ascent |
| float | Descent |
| float | Leading |
| int | Kerning |
| struct FFontImportOptionsData | ImportOptions |
| int | NumCharacters |
| unsigned char | UnknownData02 [0x4] |
| TArray< int > | MaxCharHeight |
| float | ScalingFactor |
| int | LegacyFontSize |
| struct FName | LegacyFontName |
| struct FCompositeFont | CompositeFont |
| unsigned char | UnknownData03 [0x50] |
| Public Attributes inherited from UObject | |
| void * | VTableObject |
| int32_t | ObjectFlags |
| int32_t | InternalIndex |
| class UClass * | Class |
| FName | Name |
| class UObject * | Outer |
Additional Inherited Members | |
| Public Member Functions inherited from UObject | |
| std::string | GetName () const |
| std::string | GetFullName () const |
| bool | IsA (UClass *cmp) const |
| void | ProcessEvent (class UFunction *function, void *parms) |
| void | ExecuteUbergraph (int EntryPoint) |
| Static Public Attributes inherited from UObject | |
| static FUObjectArray * | GObjects |
|
inlinestatic |
| float Ascent |
| TArray<struct FFontCharacter> Characters |
| struct FCompositeFont CompositeFont |
| float Descent |
| float EmScale |
| EFontCacheType FontCacheType |
| struct FFontImportOptionsData ImportOptions |
| int IsRemapped |
| int Kerning |
| float Leading |
| struct FName LegacyFontName |
| int LegacyFontSize |
| TArray<int> MaxCharHeight |
| int NumCharacters |
| float ScalingFactor |
| TArray<class UTexture2D*> Textures |
| unsigned char UnknownData00[0x8] |
| unsigned char UnknownData01[0x7] |
| unsigned char UnknownData02[0x4] |
| unsigned char UnknownData03[0x50] |


BWCTL Version 1.4.2rc3
(Bandwidth Control)
http://e2epi.internet2.edu/bwctl/
$Date$
BWCTL is a command line client application and a scheduling and policy
daemon that wraps the throughput testing tools Iperf, Thrulay, and Nuttcp. These tests can measure
maximum TCP bandwidth, with various tuning options available, or, by doing a
UDP test, the delay, jitter, and datagram loss of a network.
The bwctl client application works by contacting a bwctld process
on the two test endpoint systems. BWCTL will work as a 3-party application.
The client can arrange a test between two servers on two different systems. If
the local system is intended to be one of the endpoints of the test, bwctl
will detect whether a local bwctld is running and will handle the required server
functionality if needed. bwctld manages and schedules the resources of the host
on which it runs. A more detailed description of the architecture is available
in the architecture documentation.
The bwctl client is used to request the type of throughput
test wanted. Furthermore, it requests when the test should be executed. bwctld
either responds with a tentative reservation or a test denied message.
Once bwctl is able to get a matching reservation from both bwctld
processes (one for each host involved in the test), it confirms the reservation.
Then, the bwctld processes run the test and return the results.
The results are returned to the client from both sides of the test. Additionally,
the bwctld processes share the results from their respective sides
of the test with each other.
BWCTL is used to enable non-specific throughput tests to a host without
having to give full user accounts on the given system. Users want the ability
to run throughput tests to determine the achievable or available bandwidth
between a pair of hosts. It is often useful to test to multiple points
along a network path to determine the network characteristics along that
path. Typically, users who want to do this path decomposition have to contact
the network/system administrators that control the hosts along the path
directly. The administrator needs to either run half of the test for the
user or provide a user account on the host. Also, network paths of interest
usually are controlled by multiple administrators. These hurdles have made
this kind of testing difficult in practice.
BWCTL was designed to help with this problem. It allows an administrator
to configure a given host as an Iperf, Thrulay or Nuttcp
endpoint that can be shared by multiple users without concern that those users
will interfere with each other. Specific policy limits can be applied to
specific users, and individual tests are scheduled so they will not interfere
with each other. BWCTL allows the administrator to classify incoming
connections based upon a user name and AES key (generated by a pass phrase)
combination or, alternatively, based upon an IP/netmask. Once the connection is
classified, the bwctld can determine the exact type and intensities of
throughput tests that will be allowed. (More details on the policy controls
can be found in the bwctld.limits(8)
manual page.)
What's Changed Since Version 1.2a
- Allows for different throughput testing tools. Currently supported are Iperf, Thrulay and Nuttcp. Use the -T option on bwctl to specify which throughput testing tool to use. Use bwctl -h to see which are supported.
- NOTE: Some of the throughput test options are not available for some of the testers. BWCTL does not support UDP tests, changing the output format or changing the output units with either Nuttcp or Thrulay.
- Allows throughput tests to use multiple, parallel streams. This can be specified with the -P option in the bwctl client.
- Allows for UDP tests with bandwidth limits of higher than 4.3Gbps. This only works with 1.3 clients and servers.
- Allows for comma-separated value output for Iperf. Add "-y c" to the bwctl command line client to use it.
- Allows administrators to define scripts to run at the completion of each test, allowing for results to be stored in a database, accounting tracking or any number of other tasks.
- Improves robustness of time/scheduling.
- Improves error handling of Iperf children processes.
- Improves error messages for failure conditions.
What's Changed Since Version 1.1b
- Added -f option to bwctld to allow it to run with root permissions.
- Added better usage() messages and more information to several user prompts.
- Fixed bug that caused all server side errors to be reported incorrectly be the client.
- Fixed bwctld bug that disabled srcnode option.
- Ported to Solaris.
- Ported to OS X.
- Removed NTP system call dependency. Added allow_unsync options.
- Increased default -L value for bwctl.
- Added messages to data output to indicate if Iperf was killed.
- Modified all config options to have '_' between words.
Features
-
Supports version 2.0.x of Iperf.
-
Supports version 5.3.1 of Nuttcp.
- NOTE: BWCTL does not support UDP tests, changing the output format or changing the output units with Nuttcp.
-
Includes built-in support for Thrulay.
- NOTE: BWCTL does not support UDP tests, changing the output format or changing the output units with Thrulay.
-
Full IPv6 support. No options needed. If the target of a test is specified
by a DNS hostname, and that name has both an IPv4 and an IPv6 address defined,
the bwctl command line application prefers the IPv6 address.
-
Data from both sides of the test is returned so that sending rate can be
compared with receiving rate.
-
3-Party communication is supported. The client does not have to be on one
of the test endpoint hosts.
-
A local bwctld is not required. bwctl will detect if there
is a local bwctld and use it if it is there; bwctl will mimic the
missing functionality if needed.
-
Port ranges for the bwctld peer connections can be specified to
allow bwctld to work in firewall environments.
-
Port ranges for the throughput tests can be specified to allow passive
monitoring to characterize the test streams more easily.
-
Limits the types of throughput tests that can be run. Sending a set amount of
data is not supported because BWCTL needs to know how long the test will take
before the test is started.
-
Supports dynamic TCP window size determination. (Currently, this is limited
because the bottleneck capacity is specified as a constant in the config
file. In the future, bottleneck capacity could potentially be dynamically
determined using techniques such as packet dispersion.)
Requirements
- BWCTL includes the Thrulay tester, but it would be best if Iperf 2.0.x is installed on the system.
-
The bwctld daemon prefers an NTP synchronized system clock to ensure the
two endpoints of the test are actually agreeing to the same scheduled time
window for test execution.
Therefore, BWCTL requires that NTP be running to synchronize the
system clock. (See the allow_unsync configuration option
described in the bwctld.conf(8) manual page
to see how to by-pass this requirement.)
NTP should be setup correctly on the system so that bwctld
can actually fetch reasonable estimates of the time error from NTP.
For the NTP algorithms to work correctly,
NTP MUST
be configured with no fewer than 4 clocks. (See http://twiki.ntp.org/bin/view/Support/SelectingOffsiteNTPServers
for more details.)
-
gnumake may be required for the build process (see
Building the Application).
-
To get good results, the endpoints will need to be well
tuned. See http://www.psc.edu/networking/projects/tcptune/
and http://www-didc.lbl.gov/TCP-tuning/buffers.html
for some excellent tips in that regard.
Supported Systems
BWCTL has been tested most extensively on Red Hat Linux 4 and 5 systems, but
most recent versions of UNIX should work. The code cleanly compiles on FreeBSD,
Linux, and OS X.
BWCTL compiles on Solaris. However, Thrulay does not work on that
platform so is not compiled in. If anyone has any interest in updating thrulay
to work on Solaris, let us know.
Recommended Hardware
BWCTL does not have any strict hardware requirements. The limits imposed
by the specific throughput tests are more taxing to hardware than the
scheduling and policy functions added by BWCTL. The hardware requirements
are therefore a function of the specific throughput tests that are desired.
Internet2
had good luck using the following hardware to perform 1Gbps tests on the
Abilene network:
-
Intel SCB2 motherboard
-
2 x 1.266 GHz PIII, 512 KB L2 cache, 133 MHz FSB
-
2 x 512 MB ECC registered RAM (one/slot to enable interleaving)
-
2 x Seagate 18 GB SCSI (ST318406LC)
-
SysConnect Gigabit Ethernet SK-9843 SX
Building the Application
The BWCTL software uses the gnu autoconf tools to configure the
build process. BWCTL is distributed with a pre-built configure script
so the actual autoconf tools should not be needed on the target
system. (Although, gnumake may be required.) The
configure
script can be run with the --help option to determine the full set
of configurable options.
A basic build procedure would be:
% gzip -cd bwctl-$VERS.tar.gz | tar xf -
% cd bwctl-$VERS
# --prefix is only needed if you don't like the default
# (/usr/local on most systems)
% ./configure --prefix=/install/root
% make
% make install
Please report any build problems to<EMAIL_ADDRESS>Configuring bwctld
The basic procedure to configure bwctld is to create a
bwctld.conf
and, optionally, a bwctld.limits file
and a
bwctld.keys file. These files
need to be installed in the same directory that is specified with the -c
option to bwctld. The recommended directory is /install/root/etc.
(The etc directory below your install root.) There are examples
of these files in the bwctl-$VERS/conf sub directory of the
distribution.
bwctld.conf:
Used to configure basic operation of the daemon, such as server listening
port, the path for Iperf, and error logging. For a detailed description
of the options available, see the bwctld.conf(8)
manual page.
bwctld.limits:
Used to configure the policy limits for the daemon. There are two parts
to this policy: 1) authentication and 2) authorization. The authentication
is done by assigning a class to each new connection. Each class has a set
of limits associated with it. The classes are hierarchical, so a connection
must pass the limit restrictions of the assigned class as well as all parent
classes. For a detailed description of the options available, see the
bwctld.limits(8)
manual page.
bwctl.keys:
Used to associate identities with AES keys. These identities are then
mapped to a class by the bwctld.limits file. For a more detailed
description, see the
bwctld.keys(8)
manual page.
Configuring firewalls
If a firewall is enabled on the machine running bwctld, it will need to be
configured to allow incoming clients and tests. Use
this set of directions to configure the
firewall.
Configuring NTP
To ensure that tests can be run, the machine running bwctld should have its
clock synchronized using NTP. Use this set of
directions to configure NTP.
Running bwctld
The normal command line to start the daemon is:
% bwctld -c /install/root/etc
It is possible to run the daemon without a config file directory if enough
command line options are specified, but it is easier to use a config file.
To see all the available options:
% bwctld -h
More details on running the daemon, as well as a complete description of
the command line options, is available from the bwctld
manual page.
Running bwctl
The basic command line for the client is:
% bwctl [options] [-c catchhost] [-s sendhost]
The -c option indicates that the catchhost should be an
Iperf
server (think packet catcher). The -s option indicates the
sendhost
should be an Iperf client (think packet sender). At least
one of the -c/-s options must be specified. If only one of these options
is specified, the local host is assumed to be the other test endpoint.
To see a list of available options:
% bwctl -h
More details on running the client application, with a complete description
of all command line options, is available from the bwctl
manual page.
Caveats
Thrulay support is deprecated. If there is enough desire, or if someone is
willing to maintain thrulay, the functionality could be undeprecated.
Mailing Lists
There are two email lists to support this software:
-
bwctl-users
-
This is a general discussion list for users to discuss problems.
This list is monitored as bug reports should be sent here.
-
bwctl-announce
-
This list is used to announce new versions or significant developments
with regard to the software.
Information about these lists, including links to subscribe, is at
https://mail.internet2.edu/wws/lists/engineering.
Author
Jeff Boote
<EMAIL_ADDRESS>Internet2
Aaron Brown
<EMAIL_ADDRESS>Internet2
Acknowledgments
The following individuals have greatly aided in the development, testing, or
debugging of BWCTL:
- Shumon Huque (UPenn)
- Paul Hyder (NOAA)
- Warren Matthews (GaTech)
- Sean Peisert (SDSC)
- Chris Tracy (MAX)
$Id$


This platform is hosted on the openshift servers by redhat. Please don't try to attack the server you are only allowed to use the labs
By this labs you can practice with the topics of the webmip blog!


{% extends "emails/base.html" %} {% block content %}
Your request for prepared meals has been selected!
Please note that this does not mean your meal delivery has been scheduled, meal deliveries are scheduled once a volunteer chef signs up to cook for a request.
We will contact you as soon as a chef signs up to cook your meals.
Thank you, and stay safe!
{% endblock %}


pyRT_DISORT.observation¶
This module contains tools to hold and compute quantities commonly found in an observation.
Angles¶
Angles
is the fundamental class for holding on to the angular geometry
from an observation. pyRT_DISORT also includes functions to help create its
input, along with functions to create instances of Angles
under
certain special cases.
-
class
observation.
Angles
(incidence, emission, azimuth, beam_azimuth)[source]¶ A data structure that contains angles required by DISORT.
It accepts both the incidence and azimuth angles of the incident beam as well as emission and azimuth angles from an observation. It holds these values and computes both \(\mu_0\) and \(\mu\) from these angles.
This class can compute all angular quantities required by DISORT at once, even multiple observations. Both
incidence
andbeam_azimuth
must have the same shape (the “observation shape”). Bothemission
andazimuth
must have that same shape with an additional axis at the end, though the length of that axis can be different for both of these inputs.- Parameters
incidence (numpy.ndarray) – Incidence (solar zenith) angles [degrees]. All values must be between 0 and 180 degrees.
emission (numpy.ndarray) – Emission (emergence) angles [degrees]. All values must be between 0 and 180 degrees.
azimuth (numpy.ndarray) – Azimuth angles [degrees]. All values must be between 0 and 360 degrees.
beam_azimuth (numpy.ndarray) – Azimuth angles of the incident beam [degrees]. All values must be between 0 and 360 degrees.
- Raises
TypeError – Raised if any of the angles are not a numpy.ndarray.
ValueError – Raised if any of the input arrays contain values outside of their mathematically valid range, or if the input arrays do not have the same observation shape.
- Return type
None
Warning
- UserWarning
Issued if any values in
incidence
are greater than 90 degrees.
See also
phase_to_angles
Create instances of this class if the phase angles are known, but the azimuth angles are unknown.
sky_image
Create instances of this class from a single sky image.
Notes
DISORT wants a float for
UMU0
andPHI0
; it wants a 1D array forUMU
andPHI
. Selecting the proper indices from the observation dimension(s) is necessary to get these data types.Examples
For a (3, 5) sky image with a single incident beam:
>>> import numpy as np >>> incidence_ang = np.array([30]) >>> beam_azimuth = np.array([40]) >>> emission_ang = np.linspace(30, 60, num=3)[np.newaxis, :] >>> azimuth_ang = np.linspace(20, 50, num=5)[np.newaxis, :] >>> angles = Angles(incidence_ang, emission_ang, azimuth_ang, beam_azimuth) >>> print(angles) Angles: mu = [[0.8660254 0.70710678 0.5 ]] mu0 = [0.8660254] phi = [[20. 27.5 35. 42.5 50. ]] phi0 = [40]
For a sequence of 50 images at a fixed position over a period time where the incidence angle and beam azimuth angle of each image varies:
>>> incidence_ang = np.linspace(30, 35, num=50) >>> beam_azimuth = np.linspace(40, 50, num=50) >>> emission_ang = np.broadcast_to(np.linspace(30, 60, num=3), (50, 3)) >>> azimuth_ang = np.broadcast_to(np.linspace(20, 50, num=5), (50, 5)) >>> angles = Angles(incidence_ang, emission_ang, azimuth_ang, beam_azimuth) >>> print(angles.mu0.shape, angles.mu.shape, angles.phi.shape) (50,) (50, 3) (50, 5)
For a (40, 50) image where each pixel has its own set of angles:
>>> ang = np.outer(np.linspace(1, 2, num=40), np.linspace(10, 40, num=50)) >>> expanded_ang = np.expand_dims(ang, -1) >>> angles = Angles(ang, expanded_ang, expanded_ang, ang) >>> print(angles.mu0.shape, angles.mu.shape, angles.phi.shape) (40, 50) (40, 50, 1) (40, 50, 1)
-
property
emission
¶ Get the input emission angles [degrees].
-
property
incidence
¶ Get the input incidence angles [degrees].
-
property
mu
¶ Get \(\mu\)—the cosine of
emission
.Notes
Each element along the observation dimension(s) is named
UMU
in DISORT.
-
property
mu0
¶ Get \(\mu_0\)—the cosine of
incidence
.Notes
Each element along the observation dimension(s) is named
UMU0
in DISORT.
-
property
phi
¶ Get \(\phi\)—the azimuth angles [degrees]. This is the same as the input to
azimuth
.Notes
Each element along the observation dimension(s) is named
PHI
in DISORT.
-
property
phi0
¶ Get \(\phi_0\)—the azimuth angles of the incident beam [degrees]. This is the same as the input to
beam_azimuth
.Notes
Each element along the observation dimension(s) is named
PHI0
in DISORT.
make_azimuth¶
-
observation.
make_azimuth
(incidence, emission, phase)[source]¶ Construct azimuth angles from a set of incidence, emission, and phase angles.
- Parameters
incidence (numpy.ndarray) – Incidence (solar zenith) angles [degrees]. All values must be between 0 and 180 degrees.
emission (numpy.ndarray) – Emission (emergence) angles [degrees]. All values must be between 0 and 180 degrees.
phase (numpy.ndarray) – Phase angles [degrees]. All values must be between 0 and 180 degrees.
- Raises
TypeError – Raised if any of the angles are not a numpy.ndarray.
ValueError – Raised if any of the input arrays contain values outside of their mathematically valid range.
- Return type
numpy.ndarray
Notes
It would almost always be beneficial for all of the inputs to have the same shape, but this is not strictly enforced. In any case, the input arrays must have compatible shapes.
Examples
For a random assortment of input angles:
>>> import numpy as np >>> incidence = np.array([20, 30, 40]) >>> emission = np.array([30, 40, 50]) >>> phase = np.array([25, 30, 35]) >>> make_azimuth(incidence, emission, phase) array([122.74921226,<PHONE_NUMBER>6,<PHONE_NUMBER>6])
phase_to_angles¶
-
observation.
phase_to_angles
(incidence, emission, phase)[source]¶ Construct an instance of Angles in the case where the phase angles are known (and presumably azimuth angles are unknown).
- Parameters
incidence (numpy.ndarray) – Incidence (solar zenith) angles [degrees]. All values must be between 0 and 180 degrees.
emission (numpy.ndarray) – Emission (emergence) angles [degrees]. All values must be between 0 and 180 degrees.
phase (numpy.ndarray) – Phase angles [degrees]. All values must be between 0 and 180 degrees.
- Raises
TypeError – Raised if any of the angles are not a numpy.ndarray.
ValueError – Raised if any of the input arrays contain values outside of their mathematically valid range.
- Return type
Warning
- UserWarning
Issued if any values in
incidence
are greater than 90 degrees.
Notes
It would almost always be beneficial for all of the inputs to have the same shape, but this is not strictly enforced. In any case, the input arrays must have compatible shapes.
Examples
For a random assortment of input angles:
>>> import numpy as np >>> incidence = np.array([20, 30, 40]) >>> emission = np.array([30, 40, 50]) >>> phase = np.array([25, 30, 35]) >>> angles = phase_to_angles(incidence, emission, phase) >>> print(angles) Angles: mu = [[0.8660254 ] [0.76604444] [0.64278761]] mu0 = [0.93969262 0.8660254 0.76604444] phi = [[122.74921226] [129.08074256] [131.57329276]] phi0 = [0. 0. 0.]
sky_image¶
-
observation.
sky_image
(incidence, emission, azimuth, beam_azimuth)[source]¶ Create an instance of Angles from a typical sky image—that is, a single incidence and beam azimuth angle are known, and the observational geometry defines a 1D array of emission and azimuth angles.
- Parameters
incidence (float) – Incidence (solar zenith) angle [degrees]. Value must be between 0 and 180 degrees.
emission (numpy.ndarray) – Emission (emergence) angle [degrees]. All values must be between 0 and 180 degrees.
azimuth (numpy.ndarray) – Azimuthal angle [degrees]. All values must be between 0 and 360 degrees.
beam_azimuth (float) – Azimuth angle of the incident beam [degrees]. Value must be between 0 and 360 degrees.
- Raises
TypeError – Raised if any of the angles are not a numpy.ndarray.
ValueError – Raised if any of the input arrays contain values outside of their mathematically valid range, or if the input arrays do not have the same observation shape.
- Return type
Warning
- UserWarning
Issued if any values in
incidence
are greater than 90 degrees.
Examples
For a (3, 5) sky image with a single incident beam:
>>> import numpy as np >>> incidence_ang = 30 >>> beam_az = 40 >>> emission_ang = np.linspace(30, 60, num=3) >>> azimuth_ang = np.linspace(20, 50, num=5) >>> angles = sky_image(incidence_ang, emission_ang, azimuth_ang, beam_az) >>> print(angles) Angles: mu = [[0.8660254 0.70710678 0.5 ]] mu0 = [0.8660254] phi = [[20. 27.5 35. 42.5 50. ]] phi0 = [40]
Spectral¶
Spectral
is the fundamental class for holding on to the spectral
information from an observation. pyRT_DISORT also includes functions to help
create instances of Spectral
under certain special cases.
-
class
observation.
Spectral
(short_wavelength, long_wavelength)[source]¶ A data structure that contains spectral info required by DISORT.
It accepts the short and long wavelength from an observation and computes their corresponding wavenumber.
- Parameters
short_wavelength (numpy.ndarray) – The short wavelength [microns] of each spectral bin.
long_wavelength (numpy.ndarray) – The long wavelength [microns] of each spectral bin.
- Raises
TypeError – Raised if either of the wavelengths are not a numpy.ndarray.
ValueError – Raised if either of the input arrays are not the same shape, if any values in
short_wavelength
are not larger than the corresponding values inlong_wavelength
, or if either of the input arrays contain values outside of 0.1 to 50 microns (I assume this is the valid range to do retrievals).
- Return type
None
Notes
This class can accommodate arrays of any shape as long as they both have the same shape. If you do not plan to use thermal emission, there is probably little benefit making an instance of this class.
Examples
For an observation taken at 1 to 30 microns, with each channel having a 50 nm spectral width:
>>> import numpy as np >>> center = np.linspace(1, 30, num=30) >>> half_width = 0.025 >>> wavelengths = Spectral(center - half_width, center + half_width) >>> print(wavelengths.low_wavenumber.shape) (30,)
For an image of shape (50, 60) with the same 20 wavelengths in each pixel:
>>> center = np.linspace(1, 20, num=20) >>> half_width = 0.025 >>> wav_grid = np.broadcast_to(center, (50, 60, 20)) >>> wavelengths = Spectral(wav_grid - half_width, wav_grid + half_width) >>> print(wavelengths.low_wavenumber.shape) (50, 60, 20)
-
property
high_wavenumber
¶ Get the high wavenumber [cm -1]—the wavenumber corresponding to
short_wavelength
.Notes
Each element along the observation dimension(s) is named
WVNMHI
in DISORT. It is only needed by DISORT ifthermal_emission
is set toTrue
.
-
property
long_wavelength
¶ Get the input long wavelength [microns].
-
property
low_wavenumber
¶ Get the low wavenumber [cm -1]—the wavenumber corresponding to
long_wavelength
.Notes
Each element along the observation dimension(s) is named
WVNMLO
in DISORT. It is only needed by DISORT ifthermal_emission
is set toTrue
.
-
property
short_wavelength
¶ Get the input short wavelength [microns].
constant_width¶
-
observation.
constant_width
(center_wavelength, width)[source]¶ Create an instance of Spectral assuming the wavelengths all have a constant spectral width.
- Parameters
center_wavelength (numpy.ndarray) – The center wavelength [microns] of each spectral bin.
width (float) – The spectral width of each spectral bin.
- Raises
TypeError – Raised if
center_wavelength
is not a numpy.ndarray.ValueError – I’ll add this later.
- Return type
Examples
For an observation taken at 1 to 30 microns, with each channel having a 50 nm spectral width:
>>> import numpy as np >>> center = np.linspace(1, 30, num=30) >>> width = 0.05 >>> wavelengths = constant_width(center, width) >>> print(wavelengths.low_wavenumber.shape) (30,)


Part 2
SUNDAY
All mystical experience is coincidence;
and vice versa, of course.
—Tom Stoppard,
Jumpers


We now help you to map your financial journey to personal wealth.
The following tutorials enable you to broaden and test your financial knowledge.
See your current progress on the right
Ok great. We have now identified your personal situation. Let’s continue with your travel destination.
In other words, let’s find out, which finals goals you what to achieve in the future.
Following pages just give an overview of the topics of this stage.
* Exemplary overview stage content & steps
* Exemplary overview stage content & steps
* Exemplary overview stage content & steps
* Exemplary overview stage content & steps


- Figure 1: Pageviews above and below 1%.
- Figure 2: Google Analytics' pageviews for the Graham Resource Center.
- Figure 3: Screenshot of the faculty page for the current library website.
- Figure 4: Screenshot of the resources available for dissertations and theses.
- Figure 5: Screenshot of a sample database page, providing links to other resources using the same subjects and formats.
- Figure 6: Assessment of the Access & Usage text from readability-score.com.
- Figure 7: Secondary header on the current library website.
- Figure 8: IIT main site secondary header.
- Figure 9: Proposed header for new library site.
- Figure 10: New website header with student subheading displayed.
- Figure 11: Databases sorted for the psychology subject.
- Figure 12: Databases sorted for the business subject..
- Figure 13: HawkEye prototype—initial home page.
- Figure 14: HawkEye prototype—error page.
- Figure 15: HawkEye prototype revised home page.
- Figure 16: Current home page, book-related items.
- Figure 17: Current home page, database items
- Figure 18: New website home page.


This is the last lesson in this course. It discusses topics mostly
related to object-oriented programming in Nemerle. This should be fairly
easy for C# programmers, while people with Java/C++ background will
have a slightly harder time.
This lesson again borrows topics from Grokking Nemerle.
In Nemerle, types can live in namespaces. If type X is defined in
namespace Y, then its full name is Y.X. It is a good idea to put
all your code in some unique namespace if you're going to distribute it,
to avoid name clashes. All classes in the Base Class Library live in some
namespace (mostly in System
and its sub-namespaces).
The syntax for defining namespaces is:
namespace FooBarCorp.TurboLib {
class SomeClass { }
}
The full name of SomeClass
is FooBarCorp.TurboLib.SomeClass
.
If this is going to be a library, it should be placed in FooBarCorp.TurboLib.dll
.
One of the great advantages of Nemerle or C# over Java is that you don't need to
create any folder that matches the name of the namespace. Indeed, you can create
more than one namespace in a file:
namespace FuBar {
namespace Example {
// This is FuBar.Example
}
}
namespace OtherFoo {
// This is just OtherFoo
}
```
Nemerle requires all objects to be referenced using their fully qualified
name. To use <code>SomeClass</code>, you would have to reference <code>FooBarCorp.TurboLib</code>.
But, to avoid typing <code>FooBarCorp.TurboLib</code> again and again to access
its classes, there is a special <code>using</code> directive that ''imports''
the given namespace. So the following is valid:
```nemerle
using FooBarCorp.TurboLib;
def c = SomeClass ();
(Code inside the FooBarCorp.TurboLib
namespace doesn't require
using FooBarCorp.TurboLib;
-- that's done automatically.)
You can also use:
using FooBarCorp;
def c = TurboLib.SomeClass ();
One of the features Nemerle has is the ability to import a namespace and
use the namespaces inside it without qualifying them with the parent name.
In C#, you would have to add one or more using
directives to
for the classes you wish to use to get this effect.
Another form of the using
directive allows you to give a
shorter name to a namespace:
using TL = FooBarCorp.TurboLib;
def c = TL.SomeClass ();
Finally, using
is not restricted only to namespaces -- with
using
you can also reference a class or module so you can
use its static members:
using System.Console;
WriteLine ("Hey, we just used Console.WriteLine without writing Console!");
Enums are like restricted variants. Enums contain a list of options, and
cannot have methods, fields, or constructors. Example:
enum Color {
| Red
| Green
| Blue
}
def string_of_color (e) {
match (e) {
| Color.Red => "red"
| Color.Green => "green"
| Color.Blue => "blue"
}
}
System.Console.WriteLine (string_of_color (Color.Red));
Enums are internally represented as integers, which makes them more efficient
than variants. It also means you can convert integers to enums, but beware:
if an integer doesn't represent a valid enum option, strange things can happen,
so it's better to check a enum variable for allowed ranges before using it. For example;
System.Console.WriteLine (string_of_color (13 :> Color));
This will raise MatchFailure
exception.
However, the way enums work can help on some situations. One of the most used
is to combine two or more values into one, using the | (OR) operator. For this,
you must use values that do not overlap. Powers of 2 (1, 2, 4, ...) are ideal,
because their individual bits do not coincide (in binary, 1 => 0b001, 2 => 0b010,
4 => 0b100), so the | operator can use them unambigously. The Mono and .NET
guidelines also state that this type of enum should be marked with the
Flags attribute:
using System;
[FlagsAttribute]
enum Seasons {
| Winter = 0b0001
| Spring = 0b0010
| Summer = 0b0100
| Fall = 0b1000
| Autumn = Fall
| AllSeasons = Winter + Spring + Summer + Fall
}
def seasons = Seasons.Winter | Seasons.Fall;
Console.WriteLine ($"Seasons: $(seasons.ToString())");
/* Output:
Seasons: Winter, Autumn
*/
As you can see in this example, you can also use more than one alias for the
same value, and even create combinations of values in the enum, like we have
done with AllSeasons
. Also, since we were able to use the
[FlagsAttribute]
, we saved ourselves the trouble of having to write
our own string_of_season function.
Normally, when you pass some value as a function parameter, a copy
of the value is created. This is call-by-value, and is preferred
because it makes certain that the function cannot modify the calling
code's values. But sometimes you do want the function to change the
original value passed to it, not the copy. This is possible by passing
the parameter using the ref
keyword. Such a parameter is
passed by reference, which means that when the parameter value is
changed by the function, the calling code sees it.
class C {
public static Inc (x : ref int) : void
{
x++;
System.Console.WriteLine (x);
}
public static Main () : void
{
mutable q = 13;
Inc (ref q);
Inc (ref q);
}
}
/* Output:
14
15
*/
First, you need to add a ref
annotation to the parameter type when
you declare the function. When you call the function, you need to pass
a mutable value (a local variable or a mutable field), and prefix it
with ref
keyword. Be aware that this just works with value types.
In Mono/.NET, there is a strong divison between reference and value types.
When you pass a reference type (object) as a parameter, you are only
passing a reference to an object, so every change to the object in the
function will also change the calling object. Value types (numbers, strings)
are always copied when passed, so you need the ref keyword to change this
default behavior.
There is also a similar out
modifier. It means that the function
is not going to read what's in the parameter, it is just going to return
some value through it. In C# this is handy when you want to return more
than one value from a function. In Nemerle, Nemerle_for_OOP_Programmers_Week_3#Tuples
are used for the same purpose, so the use of out parameters is much less
common. Anyway, the usage is:
class C {
public static read_line (line : out string) : bool
{
line = System.Console.ReadLine ();
if (line == "quit") false
else true
}
public static Main () : void
{
mutable s = null;
while (read_line (out s)) {
System.Console.WriteLine (s);
}
}
}
This feature comes from Python. You can name the parameters in a
function call, which allows putting them in a different order than
in the definition. This can make your code more readable, especially
when using default parameters.
frobnicate (foo : int,
do_qux : bool,
do_baz : bool,
do_bar : bool) : int
{
// this is completely meaningless
if (do_qux && !do_baz) foo * 2
else if (do_bar) foo * 7
else if (do_baz) foo * 13
else 42
}
Main () : void
{
// Parameters' names can be omitted.
def res1 = frobnicate (7, true, false, true);
// This is the intended usage -- the first
// (main) parameter comes without a name
// and the following flags with names
def res2 = frobnicate (7, do_qux = true,
do_baz = false,
do_bar = true);
// You can however name every parameter:
def res3 = frobnicate (foo = 7, do_qux = true,
do_baz = false, do_bar = true);
// And permute them:
def res3 = frobnicate (do_qux = true, do_bar = true,
do_baz = false, foo = 7);
// You can also omit names for any number of leading
// parameters and permute the trailing ones.
def res2 = frobnicate (7, true,
do_bar = true,
do_baz = false);
()
}
The rules behind named parameters are simple:
- Named parameters must come after all unnamed (positional) parameters
- Positional parameters are assigned first
- The remaining parameters are assigned based on their names
Named parameters can be used only when names of parameters are known
(which basically means they do not work in conjunction with functional
values).
This feature is particularly useful with default parameters:
frobnicate (foo : int, do_qux : bool = false,
do_baz : bool = false,
do_bar : bool = false) : int { ... }
frobnicate (3, do_baz = true);
frobnicate (3, do_baz = true, do_qux = true);
You can overload existing operators or add new ones simply by specifying
them as a static method in some type. The name of method must be quoted
with the @
operator. For example, the following class definition:
class Operand {
public val : int;
public this (v : int) { val = v }
public static @<-< (x : Operand, y : Operand) : Operand {
Operand (x.val + y.val);
}
}
contains the <-<
binary operator processing Operand
objects. It can be used like:
def x = Operand (2);
def y = Operand (3);
def z = x <-< y;
assert (z.val == 5);
Unary operators can be created by giving only one parameter to the method.
It is also possible to overload built-in operators like +
and
-
. Some of the classes exposed in the Base Class Library (like
Point) use this operator overloading. If you use them, you should also
provide another way to get its functionality, to mantain compatibility
with other languages. For example:
using Nemerle.Utility;
[Record]
class Vector {
[Accessor] x : double;
[Accessor] y : double;
[Accessor] z : double;
public Add (v : Vector) : Vector {
Vector (this.X + v.X, this.Y + v.Y, this.Z + v.Z)
}
public static @+ (v1 : Vector, v2 : Vector) : Vector {
v1.Add (v2)
}
}
def v1 = Vector (1, 2, 3);
def v2 = v1 + v1;
def v3 = v2.Add (v1);
The .NET Framework supports only single inheritance. This means that
any given class can derive from just one base class. However, a class
may sometimes be required to be two or more different things, depending
on context. .NET supports this (just like Java) through interfaces. An
interface is a contract specifying a set of methods that given class must
implement. A class can implement any number of interfaces, in addition
to deriving from some base class.
Implementing an interface implies subtyping it. That is, if you have a
class A implementing interface I, and method taking I as
parameter, then you can pass A as this parameter.
Interfaces most commonly state some ability of type. For example, the
ability to convert itself to some other type, or to compare with some
other types.
using Nemerle.IO;
interface IPrintable {
Print () : void;
}
class RefrigeratorNG : Refrigerator, IPrintable
{
public Print () : void
{
printf ("I'm the refrigerator!\n")
}
public this ()
{
}
}
module RP {
PrintTenTimes (p : IPrintable) : void
{
for (mutable i = 0; i < 10; ++i)
p.Print ()
}
Main () : void
{
def refr = RefrigeratorNG ();
PrintTenTimes (refr)
}
}
In the class definition, after the colon, the base class must come first,
followed by the supported interfaces in any order.
There are several macros defined in the Nemerle standard library helping
improve code safety. The most basic one is the assert
macro known
from C. It is available by default (in Nemerle.Core
), no
using
is necessary. It checks if given expression is true
and if it's not, it throws an exception stating the expression, file
and line where the problem occurred. You can also supply a second
parameter to this macro with an error message you want to include
in the exception.
There are other macros, providing requires and ensures contracts,
they are described in the wiki page about Design by contract macros.
Properties are syntactic sugar for get/set design pattern commonly found
in Java. Accessing a property looks like accessing a field, but under
the hood it is translated to a method call.
class Button {
text : string;
public Text : string {
get { text }
set { text = value; Redraw () }
}
}
def b = Button ();
b.Text = b.Text + "..."
Setter or getter blocks are not a must (of course, you need at least one :-). As we said in Week 1, for the traditional properties that just take care of saving or loading the value, the accessor macros macro is preferred over plain writing.
Indexers are another form of property, but instead of exposing a simple
field, array access syntax is used. They must take parameters, a feature
that normal properties can't have. The main use of indexers is exposing
collections to the outside, which is why the array syntax was chosen.
All .NET indexers have names, though one indexer can be marked as the
default indexer (well, in fact one indexer name is marked as default,
but there can be several indexers with that name, subject to the regular
overloading rules).
For example, the System.Hashtable
default indexer is called
Item
and System.String
one is called Chars
.
The C# language allows definition of a default indexer only. Nemerle allows
you to define other indexers (like VB.NET). In the current release, the
default indexer is always Item
.
class Table {
store : array [array [string]];
public Item [row : int, column : int] : string
{
get {
System.Console.WriteLine ($"get ($row, $column)");
store[row][column]
}
set {
System.Console.WriteLine ($"set ($row, $column)");
store[row][column] = value
}
}
public this ()
{
store = array (10);
for (mutable i = 0; i < store.Length; ++i)
store [i] = array (10);
}
}
def t = Table ();
t[2, 3] = "foo";
t[2, 2] = t[2, 3] + "bar";
/* Output:
set (2, 3)
get (2, 3)
set (2, 2)
*/
Delegates are half-baked functional values. There is little place for
using delegates in Nemerle itself, because it supports true functional
values. However other .NET languages all speak delegates, so they are
good way to expose Nemerle functional values to them, and vice versa.
Delegates are in essence named functional types. They are defined with
delegate
keyword:
delegate Foo (_ : int, _ : string) : void;
delegate Callback () : void;
Later, the delegate name can be used to construct delegate instances.
Any functional value of corresponding type can be used to create a
delegate instance (local functions and lambda expressions in particular):
def my_fun (i : int, s : string) {
// do something with i and s
}
def my_Foo_delegate = Foo (my_fun);
def another_Foo_delegate = Foo (fun (i, s) { ... use i, s ... });
Delegate instances can be invoked using standard function call syntax,
as well as the Invoke
special method. Please consult the Base
Class Library documentation (on MSDN) for details.
The +=
operator has special meaning on delegate instances --
it calls the System.Delegate.Combine
method that makes one
function that calls two others in sequence. This operator is probably
more useful with events.
module X {
some_fun () : void
{
mutable f = Foo (fun (_, _) {});
f (3, "foo"); // same as f.Invoke (3, "foo");
f += fun (_, s) { System.Console.WriteLine (s) };
f (42, "bar");
}
}
Please note that creating a delegate is indeed creating a new class, so
it can have the same level of visibility that you assign to any other class.
You should also write delegates as stand-alone classes to prevent nesting.
You also have to think about accessibility when working with delegates.
There is a requirement that if an event has a certain level of accessibility,
then its delegate must have equal or greater accessibility.
This is a general rule in Nemerle (taken from C#), that when you define
an entity E of type T, then access rights on E cannot be more permissive
than access right on T. Otherwise it would be possible that a user would
have access to E, but he wouldn't be able to use it, because the T
would be inaccessible.
Events are specialized properties for delegates. They are used in a GUI
system for connecting signals (setting function to call when a button is
pressed, etc.). They can be also used to call user-defined functions on
when certain things occur, like a class being loaded by the runtime system.
Events are defined like fields, but they are marked with the event
keyword, and always have a delegate type. Inside the class, events are seen
as fields of these delegate type, but outside the class only the +=
and -=
operators are available. They are used to connect and
disconnect delegates.
class Button {
public event OnClick : Callback;
}
def b = Button ();
// bind OnClick to some anonymous function ...
b.OnClick += Callback (fun () { ... })
Disconnecting is more tricky, as you cannot just do -= Callback (fun
() { ... })
. If you want to ever disconnect a delegate from an event,
you will need to store it:
def b = Button ();
def my_cb = Callback (fun () { ... });
b.OnClick += my_cb;
// ...
b.OnClick -= my_cb;
Implicit conversion from functional values to delegate instances is provided,
so you can skip delegate creation:
def b = Button ();
b.OnClick += fun () { ... }
Keep two things in mind when using events:
- An event can only be invoked within the class that exposes it. If you need any other kind of functional values that interoperate well on .NET languages, use fields of delegate types.
- Events without any method attached are considered null values, and trying to invoke them will throw an
NullReferenceException
. So before using the method syntax for invoking an event, first check whether it is null.