--- layout: post title: "Testing Serialization 2" date: 2013-10-02 11:08:18 categories: "TDD" published: true type: post featured: false author: garfieldmoore image: 'http://dd03isve2g8o3.cloudfront.net/testing-emails.jpeg' ---
My previous post on testing serialization was in-complete. Since then my tests have evolved enough to warrant another post (at least I think so).
Here's the excerpt from my previous post;
[Test]
public void Should_Serialise_across_service_boundary()
{
var s = new DataContractSerializer(typeof(BankAccount));
var account = new BankAccount() { Owner = new Person() };
s.WriteObject(new MemoryStream(), account);
}
So, what are the shortcomings I'd like to address?
However, before addressing the above issues I'd like to explain why we became interested in testing serialisation and how we failed to solve this previously.
Unlike my normal tests this is not a TDD practise. TDD is about driving your design through tests. This is not my motivation for doing this type of test.
These tests are supporting continuous integration by providing early feedback.
On the project I was designing at the time we'd spent some time tracking down the cause of defects that turned out to be serialization issues.
To address this we starting creating a comprehensive set of integration and acceptance tests. However, these took too long to run and we realised things would only get worse as our system grew.
Also, detecting these problems in integration tests increases the feedback loop. This is bad. It would be much better to find these problems sooner - preferably in unit tests.
So let's get back to the tests.
Take the following classes;
public class BankAccount
{
public string AccountNumber { get; set; }
public string SortCode { get; set; }
public Person Owner { get; set;}
public class Person
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
BankAccount and Person are simple classes, so I'm confident this will serialize correctly.
Now, how about after refactoring this to use interfaces;
public class BankAccount
{
public string AccountNumber { get; set; }
public string SortCode { get; set; }
public IParty Owner { get; set; }
}
public class Person : IParty
{
public string Name { get; set; }
public DateTime DateOfBirth { get; protected set; }
}
public interface IParty
{
string Name { get; set; }
}
This will now fail as the serializer has no knowledge of the interface and the Person's DateOfBirth property has a protected setter.
So here's my test;
[Test]
public void Should_Serialise_across_service_boundary()
{
GivenBankAccount();
GivenAccountHasBeenSerialised();
WhenDeserializingFromStream();
ThenAllPropertiesShouldBeSet();
}
I like to refactor my test code into methods to reduce noise and increase the intent on the code. this makes it easier to understand them later. The Givens sets up the scenario I am testing;
private void GivenBankAccount()
{
account = Builder<BancAccount>.CreateNew().Build();
person = Builder<Person>.CreateNew().Build();
account.Owner = person;
}
private void GivenAccountHasBeenSerialised()
{
storeStream = new MemoryStream();
serializer = new DataContractSerializer(typeof(BankAccount));
serializer.WriteObject(storeStream, account);
}
The When..() method deserializes the stream back into a BankAccount instance;
private void WhenDeserializingFromStream()
{
storeStream.Position = 0;
savedAccountDetails = this.serializer.ReadObject(storeStream) as BankAccount;
}
And finally, we test the deserialized object's properties are the same as the original;
private void ThenAllPropertiesShouldBeSet()
{
savedAccountDetails.ShouldNotBe(null);
savedAccountDetails.SortCode.ShouldBe(account.SortCode);
savedAccountDetails.AccountNumber.ShouldBe(account.AccountNumber);
savedAccountDetails.Owner.Name.ShouldBe(person.Name
((Person)savedAccountDetails.Owner).DateOfBirth.ShouldBe(person.DateOfBirth);
}
This test will pick up both problems; the DateOfBirth property won't be set correctly and the serializer will prompt to add the [KnownType(typeof(Person))]
attribute to the BankAccount class;
To aid re-use and reduce code clutter I've created some extension methods to serialize and de-serialize objects;
public static class SerialisationExtensions
{
public static Stream Serialize(this T target)
{
Stream storeStream = new MemoryStream();
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(storeStream, target);
return storeStream;
}
public static T DeSerialize<T>(this Stream fromStream) where T: class
{
fromStream.Position = 0;
var serializer = new DataContractSerializer(typeof(T));
return serializer.ReadObject(fromStream) as T;
}
}
This reduces code duplication in my tests. The below methods;
private void GivenAccountHasBeenSerialised()
{
storeStream = new MemoryStream();
serializer = new DataContractSerializer(typeof(BankAccount));
serializer.WriteObject(storeStream, account);
}
private void WhenDeserializingFromStream()
{
storeStream.Position = 0;
savedAccountDetails = this.serializer.ReadObject(storeStream) as BankAccount;
}
are replaced with these;
private void GivenAccountHasBeenSerialised()
{
storeStream = account.Serialize();
}
private void WhenDeserializingFromStream()
{
savedAccountDetails = storeStream.DeSerialize<BancAccount>();
}
This makes these methods redundant and we could move this code back into the test.
Creating a comprehensive suite of integration and acceptance tests did prevent our team deploying broken software. However, these were slow running tests and slowed us down.
Finding a way of moving these tests from integration to unit tests enabled us to be faster by reducing our feedback loop.
I've still got some more work to do on testing serialization but this method is easier to understand and more reliable than testing that attributes exist on your classes.


Hello.
I am a Ph.D. student at MIT CSAIL advised by David Karger. My research is driven by a desire to see better use of structured data on the web.
I am planning to graduate Summer 2014 and will try my hand at making the world a better place out in industry. If you think that might involve you, please reach out<EMAIL_ADDRESS>I'm currently working on Cascading Tree Sheets, which does for web structure what CSS did for style. I've also done a bit of natural language processing work at MIT and Google, which you're using whenever you talk to your Android phone. Prior to coming to MIT, I did R&D at BBN Technologies.
If you are learning Chinese, check out my Chinese study tools.
You should follow me on Twitter


There is another dataset has been mainly used, called TrueCar.com which was directly collected from Kaggle. The TrueCar.com dataset contains 8 features (“Price”, “Year”, “Mileage”, “City”, “State”, “Vin”, “Make”, “Model”) and about 1.2 million records. And each record has the information about the used car which is for sale.
Firstly, we considered to deal with the null records and duplicate records in this dataset. And there is no any null values and duplications has been found. To make sure the geographic analysis could be conducted successfully, checking the consistency format of the feature “State” is necessary. We capitalized state abbreviation characters and deleted the extra space.
The next data quality issue we focused on is outliers. We created a new feature (“Mileage per Year”) as in the last data cleaning part which can be used to filter unreasonable mileage records correctly. In this dataset, we used a boxplot to identify this kind of outliers.
Figure 1.2.1 Boxplot before Data Cleaning
code and dataObviously, there is an observation with extreme value in the boxplot above, and we can’t even see the box in the boxplot. Just like previously mentioned, some cars probably listed with wrong mileage and some brand new cars listed in the used cars market. We have decided to remove these kinds of records because mileage is an important feature in the used cars market.
Figure 1.2.2 Boxplot after Data Cleaning
code and dataAccording to the new boxplot above, which is the boxplot after data cleaning, it looks perfect now.
Figure 1.2.3 Mileage vs Price Scatterplot for Hyundai before Data Cleaning
code and dataThen, we have encountered another data quality issue is noise value. According to the scatter plot above, which is the mileage versus price for Hyundai before data cleaning, there are a lot of points lie around $100,000. That is ridiculous because a brand new car of Hyundai usually between $15,000 to $40,000. The used cars should even lower. And we found the same issue for many brands, such as Toyota, Honda etc.
Figure 1.2.4 Brands of Cars with a Price >= $99990
code and dataTo discover which non-expensive car brands appear in the expensive car brands, setting 99990 as a boundary, and plotting the bar chart to get the frequency for different car brands over that price boundary. The records over the price boundary and with one of the brands in “Honda”, “Toyota”, “GMC”, “Kia”, “Subaru”, “Chrysler”, “Mercury”, “Lincoln”, “Hyundai”, “Jeep”, “Chevrolet”, “Scion” were removed. In addition, we can’t remove the records of some car brands, Nissan, Ford and Lexus, because they do have expensive models.
Figure 1.2.5 Mileage vs Price Scatterplot for Hyundai after Data Cleaning
code and dataThe scatter plot above is Mileage Versus Price for Hyundai after data cleaning, it is a lot of better than before.


RaiseWithTooManyArguments
raise
can be passed more than one argument, in code this is likely to be a mistake and these rules warn when this occurs.
Rules
RaiseWithSingleArgument - FS0017
Cause
raise
is passed more than one argument e.g. raise (System.ArgumentException("Divisor cannot be zero.")) 5
Rationale
raise
being passed more than one argument (the exception to be thrown) is probably a mistake.
How To Fix
Remove the extra arguments.
Rule Settings
enabled
- A boolean property that can enable and disable this rule. (Default true)
FailwithWithSingleArgument - FS0016
Cause
failwith
is passed more than one argument e.g. failwith "Divisor cannot be zero." 5
Rationale
failwith
being passed more than one argument (the error message) is probably a mistake.
How To Fix
Remove the extra arguments.
Rule Settings
enabled
- A boolean property that can enable and disable this rule. (Default true)
NullArgWithSingleArgument - FS0018
Cause
nullArg
is passed more than one argument e.g. nullArg "Divisor cannot be zero." 5
Rationale
nullArg
being passed more than one argument (the error message) is probably a mistake.
How To Fix
Remove the extra arguments.
Rule Settings
enabled
- A boolean property that can enable and disable this rule. (Default true)
InvalidOpWithSingleArgument - FS0019
Cause
invalidOp
is passed more than one argument e.g. invalidOp "Divisor cannot be zero." 5
Rationale
invalidOp
being passed more than one argument (the error message) is probably a mistake.
How To Fix
Remove the extra arguments.
Rule Settings
enabled
- A boolean property that can enable and disable this rule. (Default true)
FailwithfWithArgumentsMatchingFormatString - FS0021
Cause
failwithf
is passed more arguments than the format string (first argument) species e.g. failwithf "%d" 5 5
Rationale
failwithf
being passed more arguments than the format string (first argument) specifies is probably a mistake.
How To Fix
Remove the extra arguments.
Rule Settings
enabled
- A boolean property that can enable and disable this rule. (Default true)
InvalidArgWithTwoArguments - FS0020
Cause
invalidArg
is passed more than two arguments e.g. invalidArg "month" "Expected value between 1 and 12"
Rationale
invalidArg
being passed more than two arguments is probably a mistake.
How To Fix
Remove the extra arguments.
Rule Settings
enabled
- A boolean property that can enable and disable this rule. (Default true)


api package¶
Submodules¶
api.helper module¶
Collection of helper functions to handle the logic for the KME.
-
api.helper.
bin_to_int
(x)¶ Convert from a binary string to a integer.
- Parameters
x (str) – Binary string to convert.
- Returns
Corresponding integer.
- Return type
int
-
api.helper.
bitstring_to_bytes
(s)¶ Converts a bitstring to a byte object.
This function is necessary as certain libraries (specifically the base64 library) accepts byte objects, not strings which are often expressed in UTF-8 or ASCII formats.
- Parameters
s (str) – Bitstring to be converted to bytes object.
- Returns
Corresponding bitstring in bytes format.
- Return type
bytes
-
api.helper.
concat_keys
(key_array)¶ Helper function to concatenate keys.
The function will concatenate integers in the same row of the 2D list
key_array
usingconcat_two_int()
.- Parameters
key_array (2D list) – 2D list of keys. Each row are the integers to be concatenated.
- Returns
List of concatenated keys in integer type. The number of keys will be
len(key_array)
(number of rows).- Return type
list
Notes
This function takes in a 2D array of keys in their integer form, and concatenates keys in the same row.
>>> arr = [[1122334455,<PHONE_NUMBER>], [3344556677,<PHONE_NUMBER>]] >>> concat_keys(arr) [4820389781632429246,<PHONE_NUMBER>9122538572]
Here,<PHONE_NUMBER>632429246 is the integer result of concatenating<PHONE_NUMBER> and<PHONE_NUMBER> with the function
concat_two_int()
. Similarly<PHONE_NUMBER>9122538572 is the result of concatenating<PHONE_NUMBER> and<PHONE_NUMBER>.
-
api.helper.
concat_two_int
(int1, int2)¶ Concatenate two integers in their 32-bit binary form.
- Parameters
int1, int2 (int) – Two integers to concatenate.
- Returns
Concatenated integer.
- Return type
int
Notes
For example: 123 in 32-bit binary is<PHONE_NUMBER>0000000000000001111011. 456 in 32-bit binary is<PHONE_NUMBER>0000000000000111001000. The binary concatenated form is<PHONE_NUMBER>000000000000000111101100000000000000000000000111001000, which in base 10 is<PHONE_NUMBER>64.
-
api.helper.
convert_int_to_uuid
(x)¶ Uses an integer as a seed to generate a UUID.
This function first hashes the integer using the hashlib.shake_128 hashing algorithm. This allows us to generate a 128bit hash that the uuid library requires as seed to generate a unique UUID.
- Parameters
x (int) – Integer as seed.
- Returns
UUID in string format.
- Return type
str
-
api.helper.
flatten_2d_list
(l)¶ Flattens a 2D list into a 1D list.
- Parameters
l (2D list) – 2D list to flatten
- Returns
Flattened list.
- Return type
1D list
-
api.helper.
int_to_base64
(x)¶ Converts an integer to a base64 string.
This is helpful in converting the encryption key, often expressed as a large base 10 integer, into base64 as it is the format required by the ETSI QKD API.
- Parameters
x (int) – Integer to convert to base 64
- Returns
Corresponding string in base64
- Return type
str
-
api.helper.
int_to_bitstring
(x)¶ Function to convert an integer to AT LEAST a 32-bit binary string.
For integer less than 32 bits, it will pad the integer with extra bits of 0s until it is of size 32bit. If the integer is greater than 32-bits, then return the binary representation with the minimum number of bits to represent the integer.
- Parameters
x (int) – Integer to convert to bitstring
- Returns
Bitstring of AT LEAST size 32-bits.
- Return type
str
Notes
Here are some example cases.
>>> int1 = 2 >>> int_to_bitstring(int1)<PHONE_NUMBER>0000000000000000000010 >>> int2 =<PHONE_NUMBER>999 >>> int_to_bitstring(int2)<PHONE_NUMBER>0001001110011100101001111111111111
In the first example, the binary representation of 2 is simply 10. Hence, the function pads the bitstring with 30 0s on the left to return a 32-bit bitstring. In the second example,<PHONE_NUMBER>999 in binary consist of > 32-bits, hence the function returns the full binary representation.
-
api.helper.
int_to_bytes
(x)¶ Converts an integer to a byte object
- Parameters
x (int) – Integer to be converted.
- Returns
Corresponding integer in bytes format.
- Return type
bytes
-
api.helper.
retrieve_keys_from_file
(number, num_key_in_each, key_file_path)¶ Helper function to retrieve keys from the actual qcrypto binary key files.
This function will parse the qcrypto binary files appropriately and return the keys in integer representation. It will also update the header files appropriately after consuming the keys. See: qcrypto github filespec.txt.
- Parameters
key_file_path (str) – Path to directory containing qcrypto key files.
number (int) – Number of keys requested
num_key_in_each (int) – How many 32bit keys each key is made of.
- Returns
List of keys in decimal (integer) form. Each row represents one key and has
num_key_in_each
integers, and there arenumber
rows.- Return type
2D list
-
api.helper.
retrieve_keys_given_uuid
(uuid_array, key_file_path)¶ Helper function to retrieve keys given the UUIDs of the keys.
This function
- Parameters
uuid_array (2D list) – 2D list of strings. Each row represents a single key, and the elements in the row are UUIDs of the individual keys that concatenate to make the full key.
key_file_path (str) – Path to directory containing qcrypto key files.
- Returns
List of keys in decimal (integer) form. Each row represents a single key, and each element in a row is the actual key that will be eventually concatenated to form the final key.
- Return type
2D list
api.kme module¶
Class implementing the Key Management Entity (KME).
-
class
api.kme.
KME
(config_path)¶ Bases:
object
Class for the KME on each node. This class also defines the related methods for manipulating the keys. Most of the configurations for the KME, such as the IP address of the web server hosting the API, IP address of the SAE etc. is stored in a
config.ini
file.- Parameters
config_path (str) – ABSOLUTE file path to config.ini that is contained in the etsi-qkd-api/api folder.
-
source_KME_ID
¶ IP address of the source (master) KME.
- Type
str
-
target_KME_ID
¶ IP address of the target (slave) KME
- Type
str
-
master_SAE_ID
¶ IP address of the master SAE (user application that requests keys)
- Type
str
-
slave_SAE_ID
¶ IP address of the slave SAE.
- Type
str
-
key_size
¶ Size of each key in bits in the KME.
- Type
int
-
max_key_per_request
¶ Maximum number of keys per request
- Type
int
-
max_key_size
¶ Maximum size of each key in bits that can be requested.
- Type
int
-
min_key_size
¶ Minimum size of each key in bits that can be requested.
- Type
int
-
max_SAE_ID_count
¶ Maximum number of additional SAEs allowed (0 at the moment).
- Type
int
-
status_extension
¶ Optional field for future use (unclear what it should be used for at the moment)
- Type
str
-
rd
¶ Object to initialize random seed and pass to UUID generator to generate UUIDs as the key IDs.
- Type
random (object, from random Python library)
-
get_key
(number, size)¶ Master function that returns the key container of keys from KME.
Function that handles the logic for retrieving the keys from qcrypto files. If the size of each key is a multiple of 32, then the keys need to be concatenated. The file retrieving is done by a helper function,
retrieve_keys_from_file()
, that actually opens the qcrypto file and retrieves the keys.- Parameters
number (int) – The number of keys requested.
size (int) – The size of each key in bits.
- Returns
Key container containing the keys requested.
- Return type
dict
- Raises
ValueError – Error if there are insufficient keys.
-
get_key_with_id
(key_ids)¶ Returns the key container of keys from KME given the key IDs.
Function will be called by the ‘slave’ application requesting for keys. The actual retrieving of keys is passed to the helper function
retrieve_keys_given_uuid()
.- Parameters
key_ids (List[dict]) – Array of dictionaries containing the key ids. Each dictionary contains one key id, in the format: { “key_id”: <key_id> }
- Returns
Key container containing the keys requested.
- Return type
dict
- Raises
KeyError – Error if the keys requested cannot be found. Thrown by
retrieve_keys_given_uuid()
.
-
get_status
()¶ Returns status of KME according to the ETSI specification.
Calls
get_stored_key_count()
and updatesstored_key_count
. This is to ensure updated key figures if a new key file is added.- Returns
Dictionary containing status properties of KME.
- Return type
dict
api.routes module¶
Functions that handle routing for the Flask web server hosting the API.
-
api.routes.
get_key
(id)¶ Method for getting key, corresponding to
Get key
in ETSI standard. Both GET and POST requests are allowed.- Parameters
id (str) – The ID (typically the IP address) of the caller. Currently any ID is allowed, hence this parameter is unused in the function call. Ideally in a multi-user setup where different IPs call the same API, the API should have logic for keeping track of different IDs, for eg. blocking off different keys for specific IPs.
- Returns
Key container containing the requested keys and key IDs, corresponding to the ETSI standard.
- Return type
json
-
api.routes.
get_key_with_id
(id)¶ Method for getting key given the key IDs, corresponding to
Get key with key IDs
method in the ETSI standard.- Parameters
id (str) – ID of the caller.
- Returns
Key container containing the requested keys and key IDs, corresponding to the ETSI standard.
- Return type
json
-
api.routes.
get_status
(id)¶ Method for getting the status of the KME. Corresponds to
Get status
method in the ETSI standard/- Parameters
id (str) – ID of the caller.
- Returns
Container containing status data formatted according to ETSI standard.
- Return type
json
-
api.routes.
home
()¶ Hello World for API set as the ‘home page URL’.
- Returns
Returns “Hello World from SpeQtral’s ETSI QKD API!” if API is running and called correctly.
- Return type
str


Biegun calls for ‘renewal’ of S. Korea-U.S. alliance: lawmaker
Stephen Biegun, Washington’s top envoy for North Korea and the nominee for deputy secretary of state, spoke Thursday of the need for a “renewal” of the Seoul-Washington alliance, a South Korean lawmaker said.
Rep. Na Kyung-won, floor leader of the main opposition Liberty Korea Party, told reporters after meeting with Biegun that she interpreted his remarks as a call for Seoul to increase its financial contribution to the upkeep of 28,500 American troops stationed in South Korea.
Na was in Washington as part of a bipartisan parliamentary delegation to deliver South Korea’s concern about U.S. demands for a sharp increase in its share of the defense costs.
The meeting was also attended by Reps. Lee In-young and Oh Shin-hwan, floor leaders of the ruling Democratic Party and minor opposition Bareunmirae Party, respectively.
“Special Representative Biegun used the expression, ‘renewal of the South Korea-U.S. alliance,’ to describe (the current conditions vis-a-vis) 1950,” Na said, referring to the year the Korean War broke out with the U.S. fighting on South Korea’s side.
“I believe he meant that these (cost-sharing negotiations) should be viewed inside the framework of a new alliance,” she said.
Oh added that Biegun projected a difficult set of negotiations ahead.
The lawmakers said they stated Seoul’s position that it will not be able to accept excessive demands from Washington and called for “fair and reasonable” negotiations based on a foundation of respect and trust.
They also said they asked Biegun to work to strengthen the alliance if confirmed as the No. 2 State Department official.
Reps. Na Kyung-won (L), Lee In-young (C) and Oh Shin-hwan, floor leaders of the Liberty Korea Party, Democratic Party and Bareunmirae Party, respectively, speak to reporters outside the U.S. State Department building in Washington on Nov. 21, 2019. (Yonhap)


Your students
There are two main pages provide as part of "Your students":
- View student details; and
Provides a list of all your students including those who have and have not registered their blog/feed. On this page you can:
- View details about the students and their blogs and posts.
- Send email to the students.
- Register or change the student's blog/feed.
- Mark posts;
If your BIM activity has set questions, this page allows you to:
- Manually allocate student posts to questions; and
- Mark student posts - including suspending posts.


CalS callose pollen CalS, synthase development Arabidopsis Fig Plant proteins tree plant wall clade data expression male analysis expressed synthases thaliana Callose contained subfamilies phylogenetic using evolutionary formation members {border-style genes protein family px;} shown #ffffff;} (GLS) cell gene model plants basal different formed microspores subfamily sequences Biology Honys Phylogenetic clades function gametophyte identified involved main sites acid amino group motifs required set synthesis total ATG Analysis GLS distribution domains mature rate supported terrestrial tube analyses conserved early evolved included pollen-expressed role second tabacum (CalS, angiosperms exine final highly number plants. (AtGSL), (Figs CalS/ Click LINK Science Sciences additional bryophytes cells deposition developmental file. groups history however, likelihood motif sequence species sperm support used ./pp.. Expression Life Physiology Research Table bicellular branch described did differences divergence evolution higher log pollen-specific proteins. px; relative rooted similar sporophytic tissues topology {font-family CalS) CalS). CalS. Evolutionary GSL), Methods Nicotiana Physcomitrella Vta bZIP bzip complex embedded essential estimated font-size generated glucan pattern pollen. positions. results storage tetrads trees (TIF) (five -.. .)). CalS; Czech I], Pollen Sequence Yang allowed analysed angiosperm based categories containing development, discrete distinct diversification domain double; evolutionarily exons gametophytes gamma invariable late lengths lower parameter plate pollen, position positions previously redundant related relationships separate sequences, sequences. sites). stages subfamilies, tobacco variation (clade ./j.-X...x ./s--- Botany CalS), Data Hafidh Interestingly, MEME Molecular Plants Protein RelTime. associated available border-color border-width bryophyte chromosome contain database degradation development. drawn functions growing large maximum measured microspore mitosis mutant pathogen patterns plants, profiles putative responsible roles scale, shared showed site. solid; specific spore substitutions suggested synthases. time timetree transcripts tree, tubes value values {font-style {font-weight Acids Amborella Annals BS, Bioinformatics CalS); Cell Development EPP Evolution FKS Fig). Foundation Genome Hong However, Huang Moreover, Pfam Physiol Thaliana Twell Zhang absent activity biosynthesis bold branching cells. cellulose closely common comparative comprised contains courier; critical cytokinesis detection developing distributed diverged division em; encoding entry form fully homologues homology hypothesis important indicated inferred inside key life lineages mRNA membrane microgametogenesis obtained permeability pollen; polysaccharide possible processes progamic pt;} response searches similarly species. spores stage stress strongly structure subfamilies. synthase-like tetrad thaliana. tricellular unknown usually version walls


This extension makes it possible to open any module expression in
module structures and expressions. A similar mechanism is also available
inside module types, but only for extended module paths (e.g. F(X).G(Y)).
For instance, a module can be constrained when opened with
module M = structlet x = 0 let hidden = 1 endopen (M:sigval x: int end)
let y = hidden
Error: Unbound value hidden
Another possibility is to immediately open the result of a functor application
let sort (type x) (x:x list) =
letopen Set.Make(structtype t = x let compare=compare end) in
elements (of_list x)
val sort : 'x list -> 'x list = <fun>
Going further, this construction can introduce local components inside a
structure,
module M = structlet x = 0
open! structlet x = 0
let y = 1
endlet w = x + y
end
module M : sigval x : int val w : int end
One important restriction is that types introduced by openstruct ...
end cannot appear in the signature of the enclosing structure, unless they
are defined equal to some non-local type.
So:
module M = structopenstructtype 'a t = 'a option = None | Some of 'a endlet x : int t = Some 1
end
module M : sigval x : int option end
is OK, but:
module M = structopen struct type t = A endlet x = A
end
Error: The type t/586 introduced by this open appears in the signature
File "extensions/generalizedopens.etex", line 3, characters 6-7:
The value x has no valid type if t/586 is hidden
is not because x cannot be given any type other than t, which only exists
locally. Although the above would be OK if x too was local:
module M: sigend = structopenstructtype t = A
end
…
openstructlet x = A end
…
end
module M : sigend
Inside signatures, extended opens are limited to extended module paths,
moduletype S = sigmodule F: sigend -> sigtype t endmodule X: sigendopen F(X)
val f: t
end
moduletype S =
sigmodule F : sigend -> sigtype t endmodule X : sigendval f : F(X).t
end
and not
open struct type t = int end
In those situations, local substitutions(see 12.7.2)
can be used instead.
Beware that this extension is not available inside class definitions:


070.2362.611
<EMAIL_ADDRESS>2-3 Business days delivery & Free Returns
Vegetables
Store
Menu
Home
Shop
Shop
Cart
Checkout
About
Blog
Contact
[{{cart.count}}] - {{cart.amount | number:0}}
Login
/
Sign Up
{{users.fullname}}
[[${#request.remoteUser}]]
Admin
[[${#request.remoteUser}]]
My Order
Wish list
Logout


When working with Ruby, methods are the basic code which tells the computer to do something. This capability is great, but what happens when you are routinely running multiple methods, and can't easily find the code you need? Classes are a functionality in Ruby which allows you to group all the methods that are applicable to certain types of objects. You can then run an instance of the Class, and all the methods are there for you. It saves time and confusion by bucketing them all together. Let's run through an example: in finance, an asset manager needs to keep track of, and be able to quickly access, multiple data points relating to any one of their portfolios. Let's build a class which will allow us to do that. We first need to initialize the class by parsing in the portfolio's name and perhaps a short code for ease of reference, along with a date that you would want the output to be as-of:
class PortfolioInfo
def initialize (name, short_code, date)
@name = name
@short_code = short_code
@date = date
end
#other code here to query underlying databases
end
Now we can write however many methods where the comments are which will take either the full portfolio name, or the short code, and use it to query underlying databases to gather information on the account as of the specified date - for example key metrics (P/E, Average Market Cap, Turnover), or generate a list of holdings as of that date. This saves us from having to write new methods every time we want to access a piece of data. We can also run this for as many portfolios and dates as we want to.


Creates a full screen overlay containing a large block of formatted text that can be scrolled with up to 8 SoftButtons defined
Function Group: ScrollableMessage
HMILevel needs to be FULL
Undocumented
- (instancetype)initWithMessage:(NSString *)message;
init(message: String)
Undocumented
- (instancetype)initWithMessage:(NSString *)message timeout:(UInt16)timeout softButtons:(nullable NSArray<SDLSoftButton *> *)softButtons;
init(message: String, timeout: UInt16, softButtons: [SDLSoftButton]?)
A Body of text that can include newlines and tabs @discussion A String value representing the Body of text that can include newlines and tabs
Notes: Maxlength=500
@property (readwrite, strong, nonatomic)
NSString *_Nonnull scrollableMessageBody;
var scrollableMessageBody: String { get set }
Gets/Sets an App defined timeout. Indicates how long of a timeout in milliseconds from the last action @discussion An Integer value representing an App defined timeout in milliseconds
Notes:Minval=0; Maxval=65535;Default=30000
@property (readwrite, strong, nonatomic, nullable) NSNumber<SDLInt> *timeout;
var timeout: (NSNumber & SDLInt)? { get set }
Gets/Sets App defined SoftButtons.If omitted on supported displays, only the
system defined
Notes: Minsize=0, Maxsize=8Close
SoftButton will be displayed
@discussion A VectorObjective-C
@property (readwrite, strong, nonatomic, nullable)
NSArray<SDLSoftButton *> *softButtons;
Swift
var softButtons: [SDLSoftButton]? { get set }


Pig Dice
Enter player1 name:
Enter player2 name:
Start Game!
Roll a dice
Hold
Player1:
Dice number:
Current Score:
Total Score:
Player2:
Dice number:
Current Score:
Total Score:
Restart Game!


dental pulp virus HCV Biology Sciences {border-style px;} #ffffff;} Hepatitis acid using nucleic []. used DNA ancient Health Life Medicine detect presence samples Anatomy blood detection human infection infections pathogens present tooth Molecular column hepatitis use amplification centrifuged infectious performed placed px; region removal sterile {font-family (.%) Analysis Dental Detection Med Para, Viral added agents detected extraction font-size positive sciences tissue AboudharamG, Amazon Blood DrancourtM. Federal Oral Pulp RNA RaoultD, Rev common discarded. double; following infected life past patients rpm sexual study Antibodies Immune National Nucleic Yersinia according antibodies border-color border-width data filtrate health patient pestis phylogenetic pulp, sample seconds solid; surgical teeth tube years {font-style {font-weight Acad Available: Body Bras Brazil. Brazilian Committee Digestive Dis. Flaviviruses Fluids: HCV. Head Hepacivirus: LGS. Microbial Natl Para Pará, Phylogenetic Physiology Proc Sci Soc State São Teeth Teeth: University access alignment analysis biological bold clinical courier; dissemination em; frozen genotype group high important information kit large males methodology minimum minutes obtained prevalence protocol pt;} pulp. removed risk small study. tissue. tree


#include <plane_3d.h>
◆ Plane3D() [1/4]
| Kratos::Plane3D::Plane3D |
( |
| ) |
|
|
delete |
◆ Plane3D() [2/4]
◆ Plane3D() [3/4]
| Kratos::Plane3D::Plane3D |
( |
array_1d< double, 3 > const & |
rNormal, |
|
|
const Point & |
rReferencePoint |
|
) |
| |
|
inline |
◆ Plane3D() [4/4]
| Kratos::Plane3D::Plane3D |
( |
const Point & |
Point1, |
|
|
const Point & |
Point2, |
|
|
const Point & |
Point3 |
|
) |
| |
|
inline |
◆ ~Plane3D()
| Kratos::Plane3D::~Plane3D |
( |
| ) |
|
|
inline |
Destructor. Do nothing!!!
◆ CalculateSignedDistance()
| double Kratos::Plane3D::CalculateSignedDistance |
( |
Point const & |
rPoint | ) |
|
|
inline |
Calculates the plane signed distance value
- Returns
- Plane signed distance value
◆ GetDistanceToOrigin()
| double Kratos::Plane3D::GetDistanceToOrigin |
( |
| ) |
|
|
inline |
Return the plane distance value
- Returns
- Plane distance value
◆ GetNormal()
Return the plane normal vector
- Returns
- Array containing the plane normal
◆ Info()
| std::string Kratos::Plane3D::Info |
( |
| ) |
const |
|
inline |
Turn back information as a string.
- Returns
- String contains information about this geometry.
- See also
- PrintData()
-
PrintInfo()
◆ KRATOS_CLASS_POINTER_DEFINITION()
| Kratos::Plane3D::KRATOS_CLASS_POINTER_DEFINITION |
( |
Plane3D |
| ) |
|
◆ PrintData()
| void Kratos::Plane3D::PrintData |
( |
std::ostream & |
rOStream | ) |
const |
|
inline |
Print geometry's data into given stream. Prints it's points by the order they stored in the geometry and then center point of geometry.
- Parameters
-
| rOStream | Stream to print into it. |
- See also
- PrintInfo()
-
Info()
◆ PrintInfo()
| void Kratos::Plane3D::PrintInfo |
( |
std::ostream & |
rOStream | ) |
const |
|
inline |
Print information about this object.
- Parameters
-
| rOStream | Stream to print into it. |
- See also
- PrintData()
-
Info()
The documentation for this class was generated from the following file:
- /home/runner/work/Documentation/Documentation/master/kratos/geometries/plane_3d.h


Class responsible for the signal concept.
More...
#include <signal.hh>
Class responsible for the signal concept.
◆ ~signal()
| osapi::process::signal::~signal |
( |
| ) |
|
◆ signal()
| osapi::process::signal::signal |
( |
int |
number | ) |
|
Constructor.
- Parameters
-
| [in] | number | - The signal number for which the instance will be built. |
◆ clearHandler()
| void osapi::process::signal::clearHandler |
( |
void |
| ) |
|
Clear any function handler set for this signal instance.
◆ equal()
| bool osapi::process::signal::equal |
( |
int |
number | ) |
|
Is the signal the same? The matching is based on the signal number.
- Parameters
-
| [in] | number | - The signal number |
- Returns
- True if signals match. False otherwise.
◆ getHandler()
| sighandler_t osapi::process::signal::getHandler |
( |
void |
| ) |
|
Get the function handler/address for this signal instance.
- Returns
- The function handler
◆ getNumber()
| int osapi::process::signal::getNumber |
( |
void |
| ) |
|
Get the signal number from the signal instance.
- Returns
- Signal number
◆ hasValidHandler()
| bool osapi::process::signal::hasValidHandler |
( |
void |
| ) |
|
Check if there is a valid handler for this signal instance.
- Returns
- True if handler valid, false otherwise
◆ isSupported()
Are signals supported, and if so, to which level?
- Parameters
-
| [out] | level | - The signal support level |
- Returns
- True if there is any support of signals in the OSAPI C platform implementation. False otherwise.
◆ setHandler()
| void osapi::process::signal::setHandler |
( |
sighandler_t |
func | ) |
|
Set handler function to call upon signal reception.
- Parameters
-
The documentation for this class was generated from the following files:


Nature Photographer Of The Year: Inspirational 2019 Winning Images
by Cecilia RodriguezThe 2019 winners of the Nature Photographer Of The Year photo competition are an inspirational reminder of the extraordinary wonder of the natural world. A black-and-white photo of two rabbits jumping high into the air taken in Kiskunsag, near the Hungarian village of Bócsa by the Hungarian nature photographer Csaba Daróczi, was chosen as the overall winner of the contest as well as the winner of the Black-and-White category. This photo was chosen, according to the judges, because of the “atmosphere, timing, beautiful light, perfect sharpness and composition.”
The Italian photographer Giacomo Redaelli, winner of the Youth category (11-17 years old) is the creator of the photo above, showing a nest of long-tailed tits getting fed by their mother.
“This photo proves that you don’t have to get extreme rare or extraordinary species in front of your camera to create a great nature photo,” says jury chairman Keith Wilson. “If you have a vision and a creative mind you can create a great shot close to home. The other remarkable thing is that it’s a black-and-white photo and because of that there’s a lot of energy emerging from it.”
The winners in the other nine categories, the special young NPOTY award and of the Fred Hazelhoff portfolio award, which was given to the beautiful photos of Romanian photographer Gheorghe Popa, were chosen from 14,000 entries from more than 73 countries, a new record for this competition.
The Nature Photography contest was created to celebrate the beauty of nature photography by the Nature Talks foundation, a non-profit organization that works with different world conservation projects.
The contest is open to professional and amateur photographers from all countries and ages starting from 10 years old and offers €25,000 in prizes, including €3,000 for the overall winner and assorted photo equipment.
The winning images are shown at the Nature Talks Photo Festival and will travel through the Netherlands, Belgium and France.
“We believe that we can show the beauty of nature worldwide by sharing the most amazing images you all make,” write the organizers. “If we learn to love nature, we’ll also protect her.”
The photo contest for the 2020 edition will open for entries on December 1, 2019, and end on May 1, 2020.
All the category winners, runners-up and highly commended photos can be found here.


Serial No.
Contribution
1
Created a toggle night mode
2
Applied animations to various sections the website
3
Created participants games section
4
Created a game
5
Listed issues from various repositories using GitHub API


--- layout: archive title: Zulip Chat Archive permalink: /stream/113488-general/topic/Notation.20for.20fields.html ---
Currently, a field is often denoted by k
, but so are integer numbers or many things. I don't know how to do \mathbb{k}
, but I have just learned that \bbK
gives 𝕂
. Would a pull request replacing all instances of a field k
by 𝕂
be welcome?
What about just capital K
? That's very common in the literature.
I've seen people use \bbK
to denote either \bbR
or \bbC
, but for general fields, I think K
is very common.
The less ambiguity the better, I would say. And we have unicode, so let's use it!
Well, are there many other uses of K
?
compact sets?
Ok, sure
Algebraists...
Sorry...
I don't really care... everything is better than \beta
(Yep, \beta
, because for some silly reason \alpha
was already used as a compact set.)
Done in #1363
{% endraw %}Last updated: Apr 24 2020 at 19:02 UTC


Locators based on css should not be tied to page layout. Page layout can be changed frequently.
Xpath locators which does not start with //
(relative) or contain more than two "/
" defines
it to be tied to page layout.
Good locators are unique, descriptive and unlikely to change.
By.xpath("/confirmation/book/message[text()]"); // Noncompliant
By.xpath("//*[@id="element_id"]");


Register now!
Name:
Username:
Email address:
Phone Number:
Password:
Confirm Password:
ADD
LOGIN HERE
ALL USERS


public interface ApnsClientMetricsListener
A metrics listener receives events from an ApnsClient
that can be used to measure the performance and
behavior of the client. Although the information sent to a metrics listener is generally available by other means,
it is provided to listeners in a simplified form for ease of consumption and aggregation.
The information provided to metrics listeners is intended only to measure the performance and behavior of an
ApnsClient
; metrics listeners should never be used to drive business logic.
ApnsClient.setMetricsListener(ApnsClientMetricsListener)
| 限定符和类型 | 方法和说明 |
|---|---|
void |
handleConnectionAttemptFailed(ApnsClient<? extends ApnsPushNotification> apnsClient)
Indicates that a previously-started connection attempt failed.
|
void |
handleConnectionAttemptStarted(ApnsClient<? extends ApnsPushNotification> apnsClient)
Indicates that the client has started an attempt to connect to an APNs server.
|
void |
handleConnectionAttemptSucceeded(ApnsClient<? extends ApnsPushNotification> apnsClient)
Indicates that a previously-started connection attempt completed successfully.
|
void |
handleNotificationAccepted(ApnsClient<? extends ApnsPushNotification> apnsClient,
long notificationId)
Indicates that a notification that was previously sent to an APNs server was accepted by the server.
|
void |
handleNotificationRejected(ApnsClient<? extends ApnsPushNotification> apnsClient,
long notificationId)
Indicates that a notification that was previously sent to an APNs server was rejected by the server.
|
void |
handleNotificationSent(ApnsClient<? extends ApnsPushNotification> apnsClient,
long notificationId)
Indicates that a notification was sent to the APNs server.
|
void |
handleWriteFailure(ApnsClient<? extends ApnsPushNotification> apnsClient,
long notificationId)
Indicates that an attempt to send a push notification failed before the notification was processed by the APNs
server.
|
void handleWriteFailure(ApnsClient<? extends ApnsPushNotification> apnsClient, long notificationId)
apnsClient
- the client that sent the notificationnotificationId
- an opaque identifier for the push notification that can be used to correlate this event
with other events related to the same notificationvoid handleNotificationSent(ApnsClient<? extends ApnsPushNotification> apnsClient, long notificationId)
apnsClient
- the client that sent the notificationnotificationId
- an opaque identifier for the push notification that can be used to correlate this event
with other events related to the same notificationvoid handleNotificationAccepted(ApnsClient<? extends ApnsPushNotification> apnsClient, long notificationId)
apnsClient
- the client that sent the notificationnotificationId
- an opaque identifier for the push notification that can be used to correlate this event
with other events related to the same notificationvoid handleNotificationRejected(ApnsClient<? extends ApnsPushNotification> apnsClient, long notificationId)
apnsClient
- the client that sent the notificationnotificationId
- an opaque identifier for the push notification that can be used to correlate this event
with other events related to the same notificationvoid handleConnectionAttemptStarted(ApnsClient<? extends ApnsPushNotification> apnsClient)
apnsClient
- the client that started the connection attemptvoid handleConnectionAttemptSucceeded(ApnsClient<? extends ApnsPushNotification> apnsClient)
apnsClient
- the client that started the connection attemptvoid handleConnectionAttemptFailed(ApnsClient<? extends ApnsPushNotification> apnsClient)
apnsClient
- the client that started the connection attemptCopyright © 2013–2018 RelayRides. All rights reserved.


val migrationInterval: Int
Sets the interval that solutions are migrated with (i.e. how many generations).
migrationInterval - Sets the interval that solutions are migrated with (i.e. how many generations).
migrationInterval


Static translations
"Static translations" are translated elements which have nothing to with content, such as "Go home" or "Submit button".
For example, the text "Website created by My Agency" at the bottom of each website page can of course be written “hardly” in the view, but it could be nice to make it available for each language of the website.
So if the user visit the website in french, this text will become "Site conçu par Mon Agence", which of course is nicer for french readers.
To manage static translation : Content > Translations
More about static translations
Static translations are stored in a language file, linked to the current theme.
This file is generated by Ionize.
Folder : /themes/your_theme/language/xxx/your_theme_lang.php
In this example, "xxx" is the language code on 2 or 3 chars, and "your_theme" is the name of your theme.
Using static translations in views
- Simply add the tag <ion:translation term=”your_term” /> in one of your view.
- Go to the Ionize menu : Content > Translations
- You will find your term and be able to write the value for each language


The USFS logs 'Current Large Incidents,' but the data are only available as a single day kmz, or a remote csv. This service will retrieve any day (with logged large incidents) and return it as geoJSON.
API 1.0 Resource ...yep, there's only one...
GET /api/v1.0/YYYY-MM-DD
SUCCESS
Returns JSON (or JSONp) object of the parameter date's large fire incidents. Return obeject has 3 child nodes:
- date: the parameter date passed to the api
- geojson: the geoJON object of the incidents. This contains 4 properties:
- area: acres of the fire
- fire_name: USFS common name
- fire_number: USFS incident ID
- report_date: USFS report date
- status: indicates that the call was a success
example successful call
ERROR - Always returns a success as long as API is up and running. Many dates have no data, so an invalid return is likely. The 'status' node if what you want to use to determine quality of return.
Returns JSON (or JSONp) object of the unsuccessful request. Return obeject has 3 child nodes:
- error: the specific error ('no data'|'not valid date (format YYYY-MM-DD)')
- parameter: the parameter as passed to the api
- status: indicates that the call was not a success
example no-data call
example invalid format call


write_animated_gif(3f) - [M_writegif_animated] Codes pixel-maps with palette into animated GIF format. Optional transparent color
Synopsis
Description
Options
Example
Author
License
subroutine write_animated_gif(filename,pixel,colormap,transparent,delay)
character(len=*),intent(in) :: filename integer,intent(in),dimension(:,:,:) :: pixel integer,intent(in),dimension(:,0:) :: colormap integer,intent(in),optional :: transparent integer,intent(in),optional :: delay
Writes gif89 image, given pixel array and color map. This version can create an animated gif.
FileName file to create or replace Pixel Pixel values 0 to ncol ColorMap Color map (RGB 0:255 for colours 0:ncol) Transparent Transparent color; optional Delay Delay time [ 1/100 of seconds]; optional
Sample call:
program demo_write_animated_gif !*************************************************************************** !> author: Jacob Williams ! ! Use the gif module to create a sample animated gif. ! !# See also !    Convert from x,y to row,col. subroutine convert(xy,row,col) implicit none ! real(wp),dimension(2),intent(in) :: xy !! coordinates integer,intent(out) :: row integer,intent(out) :: col ! row = int(-xy(2) + n/2.0_wp) col = int( xy(1) + n/2.0_wp) ! end subroutine convert !*************************************************************************** !> author: Jacob Williams ! ! Convert spherical to cartesian coordinates. subroutine spherical_to_cartesian(r,theta,xy) implicit none ! real(wp),intent(in) :: r real(wp),intent(in) :: theta real(wp),dimension(2),intent(out) :: xy ! xy(1) = r * cos(theta) xy(2) = r * sin(theta) ! end subroutine spherical_to_cartesian !*************************************************************************** end program demo_write_animated_gif !***************************************************************************
o Version 1.01, August 1999, Written by Jos Bergervoet o 2008 Jan 28: Modified by Clive Page to use stream I/O, array as colourmap. o Jacob Williams, 7/27/2014. Refactored, updated, added ability to export animated gifs. o Minor modifications to make more easily used with M_PIXEL(3f) module, 2017-July-06, John Urban
Copyright (c) 2014-2015, Jacob Williams. All rights reserved.Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
This software is provided by the copyright holders and contributors "AS IS" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright holder or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) However caused and on any theory of liability, whether in contract, strict liability, or tort (Including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
o Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. o Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. o Neither the name of the {organization} nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
| Nemo Release 3.1 | write_animated_gif (3) | May 29, 2023 |


RT @rubygems: shoes (4.0.0.pre4): Shoes is the best little GUI toolkit for Ruby. Shoes makes building for Mac, Windows, and Linux… http://t…
5/15/2015, 9:28:21 PM
Favs: 0
Retweets: 0
link--- layout: tweet ---
RT @rubygems: shoes (4.0.0.pre4): Shoes is the best little GUI toolkit for Ruby. Shoes makes building for Mac, Windows, and Linux… http://t…
5/15/2015, 9:28:21 PM
Favs: 0
Retweets: 0
link


Hello World!!! This is a Test File for git practice
Making a Change
Another change to my file to GIT
Doing a commit without the -m option
Doing git commit -v -m


def _entropy(self):
return 0.0
uniform = uniform_gen(a=0.0, b=1.0, name="uniform")
class vonmises_gen(rv_continuous):
A Von Mises continuous random variable.
def integ(p):
return log(pow(p, lam-1)+pow(1-p, lam-1))
return integrate.quad(integ, 0, 1)[0]
tukeylambda = tukeylambda_gen(name="tukeylambda")
class uniform_gen(rv_continuous):
A uniform continuous random variable.


Developing History
In {$oc.year}, {$oc.content}
Company Induction
Developing History
EmpireChem Investment Fund(EIF)
Business Philosophy
Research & Innovation
Media Contact


MIKE WILSON
→
CODE
→
LANGUAGES
→ LATIN-NUMBERS — Updated September 9, 2012
Latin Number Exercises
Latin Number exercises.
aeiouyAEIOUY
āēīōūȳĀĒĪŌŪȲ
Choose range of numbers (1-999).
Cardinal:
Ordinal:
From:
To:
Guess Numbers
Show


{% load crispy_forms_tags %} {% load url %} {% if request.user.is_authenticated and request.user.user_profile.receive_newsletter == None %}
Would you like to receive emails about announcements and updates on Grand Challenge?


%= require('html-loader!./partials/ga.html') %>
<%= require('html-loader!./partials/navigation.html') %>The Hexagon Trifecta is the ritualistic symbol that represents the Agile Squads framework and the core concepts behind it.
The triangular outline represents the balance and how all forces must be equal contributing to a purpose in order to succeed. Every member, every skill, counts.
When the triangle expands, a hexagon is revealed at the core. The hexagon represents the core values of the framework, that glues the three Squads together. Without those values, the framework collapses and fails.
At the center, lies the finite nature of the cycle. The cycle is the heartbeat and all efforts are aligned around short intervals, short deliverables and quick reaction to adaptation.


@Target(value={METHOD,ANNOTATION_TYPE}) @Retention(value=RUNTIME) @Documented public @interface Router
A method annotated with @Router may accept a parameter of type
Message
or of the expected
Message payload's type. Any type conversion supported by
SimpleTypeConverter
will be applied to
the Message payload if necessary. Header values can also be passed as
Message parameters by using the
@Header
parameter annotation.
Return values from the annotated method may be either a Collection or Array
whose elements are either
channels
or
Strings. In the latter case, the endpoint hosting this router will attempt
to resolve each channel name with the Channel Registry or with
channelMappings()
, if provided.
| Modifier and Type | Optional Element and Description |
|---|---|
String |
applySequence
Specify whether sequence number and size headers should be added to each
Message.
|
String |
autoStartup
The
SmartLifecycle autoStartup option. |
String[] |
channelMappings
The 'key=value' pairs to represent channelMapping entries
|
String |
defaultOutputChannel
Specify the channel to which this router will send messages for which destination
channels are not resolved and
resolutionRequired() is false. |
String |
ignoreSendFailures
If set to
true , failures to send to a message channel will
be ignored. |
String |
inputChannel
Specify the channel from which this router will consume messages.
|
String |
phase
Specify a
SmartLifecycle phase option. |
Poller[] |
poller |
String |
prefix
Specify a prefix to be added to each channel name prior to resolution.
|
String |
resolutionRequired
Specify whether channel names must always be successfully resolved
to existing channel instances.
|
String |
sendTimeout
Specify the maximum amount of time in milliseconds to wait when sending a reply
Message to the outputChannel . |
String |
suffix
Specify a suffix to be added to each channel name prior to resolution.
|
public abstract String inputChannel
DirectChannel
with this name will be
registered in the application context.public abstract String defaultOutputChannel
resolutionRequired()
is false.public abstract String[] channelMappings
AbstractMappingMessageRouter.setChannelMapping(String, String)
public abstract String prefix
public abstract String suffix
public abstract String resolutionRequired
If set to true
(default), a MessagingException
will be raised in case the channel cannot be resolved. Setting this attribute to false
,
will cause any unresolvable channels to be ignored.
Can be specified as 'property placeholder', e.g. ${spring.integration.resolutionRequired}
.
public abstract String applySequence
false
.
Can be specified as 'property placeholder', e.g. ${spring.integration.applySequence}
.public abstract String ignoreSendFailures
true
, failures to send to a message channel will
be ignored. If set to false
(default), a MessageDeliveryException
will be thrown instead, and if the router resolves more than one channel,
any subsequent channels will not receive the message.
Please be aware that when using direct channels (single threaded),
send-failures can be caused by exceptions thrown by components
much further down-stream.
Can be specified as 'property placeholder', e.g. ${spring.integration.ignoreSendFailures}
.public abstract String sendTimeout
Message
to the outputChannel
.
Defaults to -1
- blocking indefinitely.
It is applied only if the output channel has some 'sending' limitations, e.g.
QueueChannel
with
fixed a 'capacity'. In this case a MessageDeliveryException
is thrown.
The 'sendTimeout' is ignored in case of
AbstractSubscribableChannel
implementations.
Can be specified as 'property placeholder', e.g. ${spring.integration.sendTimeout}
.public abstract String autoStartup
SmartLifecycle
autoStartup
option.
Can be specified as 'property placeholder', e.g. ${foo.autoStartup}
.
Defaults to true
.boolean
flag.public abstract String phase
SmartLifecycle
phase
option.
Defaults Integer.MAX_VALUE / 2
for PollingConsumer
and Integer.MIN_VALUE
for EventDrivenConsumer
.
Can be specified as 'property placeholder', e.g. ${foo.phase}
.SmartLifecycle
phase.public abstract Poller[] poller
Poller
options for a polled endpoint
(PollerMetadata
).
This attribute is an array
just to allow an empty default (no poller).
Only one Poller
element is allowed.


BY EDWIN JAHIEL
RETURN TO ME (2000) *** Directed by Bonnie Hunt. Written by Hunt & Don Lake. Story by Hunt, Lake, Andrew Stern, Samantha Goodman. Photography, Liszl Kovics. Editing, Garth Craven. Production design,=
Brent Thomas. Music, Nicholas Pike. Cast : David Duchovny ( Bob Rueland), Minnie Driver (Grace Briggs), Carroll O'Connor (Marty O'Reilly), Robert Loggia (Angelo Pardipillo), Bonnie Hunt (Megan Dayton), David Alan Grier (Charlie Johnson), Joely Richardson (Elizabeth Rueland), Eddie Jones ( Emmett McFadden), James Belushi (Joe Dayton), et al. Produced by C.O. Erickson, Melanie Greene, Jennie Lew Tugend. An MGM release. 114 minutes. PG
Is Chicago thriving? More and more movies are shot there. In the real city, not "Chicago-in-Toronto," "Chicago-in-the-Studio," and all that. New releases include "High Fidelity" (a good title) and "Return to Me," (a sappy title) which make good use of their location. They could not be more different in content and style.
"Return to Me" is an old-style romantic comedy, the kind that a lot of adults who may pass up action-violence-sex films, experimental techniques, complicated stories, visual pyrotechnics, etc. would most likely enjoy. Of course, I am not talking here about film-fanatics, viewers likely to see a great deal of pictures in almost any genre.
It does not take a card-carrying movie nut to figure out "RTM." All you need to know is that its stars are David Duchovny (Bob) and Minnie Driver (Grace). The film starts by stressing unhurriedly how very happily married a couple is. Bob owns a construction company. Elizabeth ( played by Joely Richardson) is the Lincoln Park Zoo's specialist on big apes.
But since the film's female lead is Ms. Driver and not Ms. Richardson, you may guess right away that Elizabeth will have to die in an accident. That's just what happens.
Cut to chronic bad heart sufferer Grace in a hospital bed, in a life-threatening state. In crucial need of a transplant, she waits almost hopelessly for a heart to become available. One does, at the last moment. Yes, the heart is Elizabeth's.
A year goes by. Grace and Bob do not know each other. She is in fine physical shape. He is inconsolable and almost reclusive outside his work. Grace, of mixed Irish-Italian ancestry, is a charmer. She is the apple of the eye of her grandfather Marty O'Reilly (Carroll O'Connor) who has brought her up. Marty is the co-owner of O'Reilly's Irish-Italian Restaurant (sic), along with his partner, friend and chief cook Angelo Pardipillo (Robert Loggia). Grace waitresses there. The partners dote on Grace, but then everyone around loves her.
In earlier times, Grace was presumably held back from boyfriends by her formerly bad heart. Though healthy now she is haunted by the fear that any future man in her life will stay away when he discovers the scars on her chest.
Charlie, a colleague of Elizabeth's and a great friend of the couple, has been trying in vain to get Bob out of his house. He finally convinces him to meet Charlie and two girls (one a blind date for the widower) at a restaurant. Guess which eatery it turns out to be?
An amusing chain of events brings Bob and Grace together. It's attraction at first sight for both, with love not far behind.
Grace and grandpa live above the restaurant. After closing time, Marty, Angelo and two old cronies invariably get around a table to play cards and such and hold lively arguments about pop singers, baseball and other matters. Now they also become matchmakers for Grace. Egged on, the new twosome meet again and again. The relationship blooms, not sexually however. Grace says nothing about her new heart. Chest makes chaste.
The developments which will lead to the inevitable happy ending are interesting and well concocted. Comedic actress Bonnie Hunt, in the first movie she directs, does a very nice job of avoiding blatancy or supercharged scenes. She also co-scripted. And also has a major supporting role as Megan, Grace's best friend and confidante.
Megan, who has five kids, is married to burly Joe. James Belushi plays him with perfect working-class realism. The small details of life, tasks and duties in such a family come through convincingly, and amusingly. As Joe attempts to get all his children to sleep before he can make love with Megan, he exclaims "I'm trying to put you to bed. And I want to get Mother to bed too!."
"Return to Me" is appealing. It also has a plot that hangs from a thin thread, like Grace's life at the hospital, but the characters are simpatico, believable and well-played. There are several funny tidbits: a major "anonymous" donor to the zoo who keeps advertising his anonymity; Grandpa's having Grace meet a fellow "who also had a transplant" which turns out to be a hair transplant about which the man rambles on comically; an insufferable but comical blind date; and other lighthearted scenes.
I could have done without a small number of setups. The film is not free from clich=E9s. Hollywood has a thing about " hyphenated Americans, mainly Italian-Americans, Irish-Americans and Jewish-Americans. One wonders where colorfulness ends and caricature starts. On the other hand, give the movie credit for picturing Charlie, the African-American friend, with no "minoritisms" whatsoever.
Some details might have been skipped. Before meeting Bob, Grace had sent him a "thank you for my heart" letter. But what revolves around this is murky. The matchmakers' eagerness is overdone. The music track has a corny bit a la "Ave Maria" and a sudden phrase, just a Hallelujah, from Haendel's "The Messiah.". It reminds me of the saying that whenever a movie-maker does not know what to do next, he/she can throw in a Hallelujah.
In Rome, Grace tells her story to a most unlikely waiter. She also schleps from Chicago Bob's gift of a heavy bicycle -- this to a land of sleek, racing bikes. Its only function, combined with some overly cute nuns, is to be an artificial prop for the denouement.
But then, credit the movie for the subtle use of Bob's beautiful dog.
"Le mauvais gout mene au crime"(Stendhal)
Edwin Jahiel's film reviews are at: http://www.prairienet.org/ejahiel/
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Total cost
Interconnect cost
Interconnect size
Interconnect layout
Node cost
Node size
Node layout
As JSON


Company profile - Canadian Company Capabilities
Third-Party Information Liability Disclaimer
Some of the information on this Web page has been provided by external sources. The Government of Canada is not responsible for the accuracy, reliability or currency of the information supplied by external sources. Users wishing to rely upon this information should consult directly with the source of the information. Content provided by external sources is not subject to official languages, privacy and accessibility requirements.
CAPSC (CANADIAN ASSOCIATION OF PROVINCIAL SAFETY COUNCILS) SAFETY SERVICES NOVA SCOTIA
Legal Name:
CAPSC (CANADIAN ASSOCIATION OF PROVINCIAL SAFETY COUNCILS) SAFETY SERVICES NOVA SCOTIA
Operating Name:
Safety Services Nova Scotia
Mailing Address:
1-201 Brownlow AveDARTMOUTH, Nova Scotia
B3B 1W2
Location Address:
1-201 Brownlow AveDARTMOUTH, Nova Scotia
B3B 1W2
Tel.:<PHONE_NUMBER>
Fax:<PHONE_NUMBER>
Company Profile
Safety Services NS has been in the forefront of safety for 60 years. Always recognized as experts in all areas of safety and especially all safety training, we now offer consulting and business services in:
- ergonomics
- quality management and ISO 9001
- OHS management with ISO 45001 and CAN/CSA Z1000
- project management for all types of projects
- workplace testing and evaluations for noise, indoor air quality and other contaminants
- chemical management, MSDS/SDS management and writing safety data sheets
- OHS policy and program development and implementation
Full profile
Full profile
Contact information
Company description
611430 - Professional and Management Development Training
Product / Service / Licensing
Following the latest Project Management Book of Knowledge, we offer:
- initial planning, including initial budgets, scopes, work breakdown structures and Gantt charts
- project risk and issue management
- ongoing budget and scope management
- stakeholder analyses and relationship management.
We deliver projects on time, on budget and on quality.
Working to the latest ISO 45001 and CAN/CSA Z1000 standards, we can work with you to design and implement an OH&S management system that will support your managers, your supervisors and your staff, and promote injury reduction across your organization.
We offer a full range of WHMIS training, from the most basic forms to the most advanced. In addition, we will manage your MSDSs or SDSs for you, ensuring they are always up-to-date and available to your staff either on your own servers or on secure websites created just for your organization. For those of you who manufacture products either for in-house use or outside sale, we will even create detailed and comprehensive safety data sheets for you.
- sampling and analysis at certified laboratories
- staff training either for awareness or advanced "Working with asbestos"
- working with you develop Asbestos Management Plans that meet all legal requirements.
H100-Quality Control Services
R000-Professional, Administrative and Management Support Services
R199-Other Administrative and Management Support Services
U000-Educational and Training Services
U001-Lectures For Training
U008-Training/Curriculum Development
U099-Other Education and Training Services
Market profile
Industry sector market interests:
- Agriculture
- Construction
- Consumer Products
- Culture
- Environment
- Fishery
- Forestry
- Information Technology and Telecommunications
- Manufacturing
- Medical/Biotechnology/Chemical
- Mining/Petroleum/Gas
- Service Industry
- Tourism
- Transportation
- Wholesale/Retail
- Aerospace
- Defence
- Automotive
- Food and Beverage Manufacturing
- Furniture and Wood Product
- Pulp and Paper
- Plastics and Rubber Products
- Primary and Fabricated Metal
- Electrical Equipment
- Textile and Clothing
Sector information
Distribution of employees:
Based in Halifax, NS, we have staff and associates located throughout Nova Scotia. We also serve all other provinces through our broad range of networks and contacts.Third-Party Information Liability Disclaimer
Some of the information on this Web page has been provided by external sources. The Government of Canada is not responsible for the accuracy, reliability or currency of the information supplied by external sources. Users wishing to rely upon this information should consult directly with the source of the information. Content provided by external sources is not subject to official languages, privacy and accessibility requirements.
Contacts
Contact information
Description
Company description
611430 - Professional and Management Development Training
Products, services and licensing
Product / Service / Licensing
Following the latest Project Management Book of Knowledge, we offer:
- initial planning, including initial budgets, scopes, work breakdown structures and Gantt charts
- project risk and issue management
- ongoing budget and scope management
- stakeholder analyses and relationship management.
We deliver projects on time, on budget and on quality.
Working to the latest ISO 45001 and CAN/CSA Z1000 standards, we can work with you to design and implement an OH&S management system that will support your managers, your supervisors and your staff, and promote injury reduction across your organization.
We offer a full range of WHMIS training, from the most basic forms to the most advanced. In addition, we will manage your MSDSs or SDSs for you, ensuring they are always up-to-date and available to your staff either on your own servers or on secure websites created just for your organization. For those of you who manufacture products either for in-house use or outside sale, we will even create detailed and comprehensive safety data sheets for you.
- sampling and analysis at certified laboratories
- staff training either for awareness or advanced "Working with asbestos"
- working with you develop Asbestos Management Plans that meet all legal requirements.
H100-Quality Control Services
R000-Professional, Administrative and Management Support Services
R199-Other Administrative and Management Support Services
U000-Educational and Training Services
U001-Lectures For Training
U008-Training/Curriculum Development
U099-Other Education and Training Services
Market
Market profile
Industry sector market interests:
- Agriculture
- Construction
- Consumer Products
- Culture
- Environment
- Fishery
- Forestry
- Information Technology and Telecommunications
- Manufacturing
- Medical/Biotechnology/Chemical
- Mining/Petroleum/Gas
- Service Industry
- Tourism
- Transportation
- Wholesale/Retail
- Aerospace
- Defence
- Automotive
- Food and Beverage Manufacturing
- Furniture and Wood Product
- Pulp and Paper
- Plastics and Rubber Products
- Primary and Fabricated Metal
- Electrical Equipment
- Textile and Clothing


Malaysia court frees Australian grandmother in drugs case
by The Associated PressPUTRAJAYA, Malaysia — Malaysia’s top appeals court on Tuesday acquitted an Australian grandmother who faced the death penalty in a drugs case, her lawyer said.
Defence lawyer Muhammad Shafee Abdullah said Australian national Maria Elvira Pinto Exposto was immediately taken into immigration custody.
Exposto was first exonerated by the High Court in 2017 on grounds that she didn’t know there were 1.5 kilograms (3.3 pounds) of crystal methamphetamine in her bag when she was arrested in December 2014 at Kuala Lumpur’s international airport.
But the appeals court last year overturned the lower court’s acquittal.
Her lawyer said he is now applying for her release.
The Associated Press


Responsivator
View & share how sites look at different screen sizes
an
open source project
by
John Polacek
, Lead Web Developer at
AuctionsByCellular
-
Mobile Bidding
and
Fundraising Event Services for Charities
Enter website url:
Responsivate!
view random
customize
how to get screenshots
Share link:
hide header in link


Star Trek: Insurrection A review by Joe Chamberlain
Starring Patrick Stewart; Jonathan Frakes; Brent Spiner & LeVar Burton
Jean-Luc Picard (Patrick Stewart) and the rest of the crew of the U.S.S. Enterprise are back for their third outing in the ninth film based on the 1960's series, Star Trek. Gone are Kirk, Spock and McCoy and in their wake in the very able and very talented cast from Star Trek: The Next Generation. As usual, a crisis is brewing and it is up to the crew of the Enterprise to make the galaxy safe again. This time out The United Federation of Planets and an alien race led by F. Murray Abraham are trying to move some colonists off a planet against the colonist's will. It turns out that this planet is the fountain of youth and the Federation and their alien buddies feel that is should be used for the good of everyone and not just a few hundred colonists. Of course Picard feels that this sort of treachery is wrong, so he disobeys direct orders and vows to help protect the colonists.
Insurrection is a lighter movie than the last two Star Trek films. The film focuses on the lofty question of whether the rights of society as a whole outweighs the rights of a small group. In this respect it gets back to the roots of Star Trek by disguising social commentary as science fiction. It doesn't do a bad job, other than it tries to inject too much humor into the story line. Many of the jokes are your typical inside Star Trek-Fan-Only jokes, while many of the others just fall flat.  There are only a few hundred people on this whole planet, why do they have to be moved? The explanation is that the planet has to be bombarded with deadly radiation so that this fountain of youth effect will be strong enough to help heal F. Murray Abraham's aliens who number only a couple of dozen. So the basic story line is bad enough in that we have a few hundred being booted out for a few billion, at least that's plausible. But in reality we have a few hundred being moved for the benefits of a few dozen, which makes no sense whatsoever.
The other little hiccup in logic is the inclusion of Worf (Michael Dorn), the trusty Klingon. Worf was on Star Trek: The Next Generation, so they want to include him in the films. No problem so far. Worf is now a character of Star Trek: Deep Space Nine, so the writers have to find a way to have him show up. In the last Star Trek movie, First Contact, the included Worf in a credible fashion, in this one, the writers are so lazy that the completely gloss over why he is even in the movie. What little explanation they do give is so small that you would have missed it if you weren't hanging on every word on the screen.
My minor problems with the movie aside, Star Trek: Insurrection does have an overwhelming number of good points as compared to its bad ones. While many of the jokes do miss the mark, many are pretty good, even for non-trekkies. The special effects are among the best for the Star Trek series. The action is plentiful and well done. This is a very good-looking movie. It should come as no surprise to anyone who ever watched Star Trek: The Next Generation that the acting is first rate. It is very obvious that these actors have been working together for over a decade. They interact with each other with a skill that few other ensemble casts can muster.
Most Star Trek fans probably will not be disappointed with this latest film in the series. If you've always hated Star Trek, there is nothing here that is going to change your mind. Star trek: Insurrection is not the best film in the series, but it is good enough to dispel the long standing tradition of the odd numbered films in the series being far inferior to the even numbered ones.
7/10
Visit The Movie Guy http://members.tripod.com/~MovieGuy/index.html
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Shows how to get started and provides an overview of the capabilities of Batfish.
Shows how to validate different types of configuration settings (NTP server, TACACS server, AAA, SNMP, etc...) using Batfish.
Shows how to analyze ACLs and firewalls rules using Batfish.
Shows a workflow to ensure changes to ACLs and firewall rules are correct and safe.
Shows how forwarding paths can be analyzed using traceroute and reachability queries.
Shows a workflow to ensure that changes to the network do not impact packet forwarding.
Shows how to analyze the impact of failures on the network and conduct Chaos Monkey style testing.
Shows how to analyze routing tables computed by Batfish.


In mathematics and computer science, graph theory studies networks of connected nodes and their properties. A graph can be used to visualize related data, or to find the shortest path from one node to another node for example.
Central concepts in graph theory are:
The PlotDevice Graph library includes algorithms from NetworkX for betweenness centrality and eigenvector centrality, Connelly Barnes’ implementation of Dijksta shortest paths (here) and the spring layout for JavaScript by Aslak Hellesoy and Dave Hoover (here). The goal of this library is visualization of small graphs (<200 elements), if you need something more robust we recommend using NetworkX.
For those of you looking for the old Graph library built on Boost,
it can still be found here.
| graph.zip (32KB) Last updated for PlotDevice 0.9 Licensed under GPL Author: Tom De Smedt |
The library has a cool example of a visual browser for WordNet.
Put the graph library folder in the same folder as your script so PlotDevice can find the library. You can also put it in ~/Library/Application Support/PlotDevice/.
graph = ximport("graph")
Outside of PlotDevice you can also just do import graph.
create(iterations=1000, distance=1.0, layout="spring", depth=True)
The create() command returns a new graph object encompassing the drawing
canvas. The network of connected nodes will originate from the center of the canvas. The
distance parameter controls the spacing between nodes and hence the size of the
graph.
By default, a spring force
layout is used to visualize the graph. Each element in the graph (or node) will
try to get away as far as possible from the others. This is the repulsive force in the
network. At the same time, there are connections (or edges) that keep nodes together.
The greater the weight of an edge the stronger it is in pulling two nodes together. This is the
attractive force in the network. You can also set the layout parameter to
‘circle’ to use a simple circle-based layout.
The forces in the network need to be calculated several times in order for the nodes’ positions to stabilize. The higher the number of iterations the better (but slower) the layout.
|
| When depth is set to True, the library will attempt to import the PlotDevice Colors library for gradient and shadow effects. |
The returned graph object has the following properties:
graph.add_node(id, radius=8, style="default", category="", root=False)
graph.add_edge(id1, id2, weight=0.0, length=1.0, label="")
You can add nodes (e.g. blocks of information you want to connect) to the graph with the graph.add_node() method. The id parameter uniquely identifies each node, it will appear as a label on each node once the graph is visualized. When the root parameter is True it will set this node as the graph’s root.
The graph.add_node() method returns a node object with the following properties:
We’ll look at the details of a node’s weight and traffic in the section on graph proximity.
You can connect two nodes with the graph.add_edge() method. It takes two node id’s,
an optional weight (ranging between 0.0 and 1.0) and an optional label to display
near the edge when it is drawn.
An edge object is returned. It has the following properties:
|
|
graph = ximport("graph") g = graph.create(iterations=500, distance=0.8) g.add_node("PlotDevice") g.add_node("Core Image", category="library") g.add_edge("Core Image", "PlotDevice") g.solve() g.draw() |
The graph object has graph.nodes and graph.edges properties that list all of the nodes and connections it contains. It also has a graph.node() and a graph.edge() method that returns nodes and edges based on id’s:
graph.node(id)
graph.edge(id1, id2)
Furthermore, a graph behaves as a dictionary with node id keys linking to node object:
for id in graph: print graph[id].style
To remove nodes and edges you can use the methods below. The graph.clear() method removes all nodes and all edges and resets the graph’s layout. This is useful when you want to dynamically reload a graph.
graph.remove_node(id)
graph.remove_edge(id1, id2)
graph.clear()
You can get access to all the nodes connected to a given node from the node.links
list. This list also has a fast node1.links.edge(node2) method that retrieves the edge
between two nodes.
Before we can draw the graph to the canvas, we first need to calculate its layout. This may take several seconds or more for graphs with many nodes. More nodes slow down the process, as do more visual elements like edge labels. The following methods are involved:
graph.prune(depth=0)
graph.update(iterations=10)
graph.solve()
graph.draw(weighted=False, directed=False, highlight=[], traffic=None)
The graph.prune() method removes orphaned nodes that have no connections . If depth is 1 it removes nodes that have one ore less connections, and so on. Pruning is often a good idea, as the less nodes there are in a graph the faster the layout is calculated.
The graph.update() method calculates a portion the total iterations. This is useful in an animation when you want the graph to slowly unfold. When the entire layout has been calculated, the graph.done property will be True.
The graph.solve() method does all the iterations at once. If you’re not running an animation you usually use this method before drawing the graph.
The graph.draw() method draws the graph to the canvas. It will originate from the canvas center (although you can nudge it horizontally or vertically with optional dx and dy parameters).
| The optional weighted parameter indicates an edge’s weight by adding a subtle shadow to it when set to True. | |
| The optional directed parameters indicates an edge’s direction with an arrow when set to True. | |
| The optional highlight parameter indicates a path between two nodes. Node id’s in the path are supplied as a list. Usually this is a value returned from the graph.shortest_path() method. | |
| The optional traffic parameter can be a number, representing the amount of top-trafficked nodes to highlight. Nodes with a high traffic have a lot of shortest paths passing through them therefore have a central role in the network. |
Layout
If you’re using the graph in an animation, you can use the graph.layout.refresh() method to trigger some new iterations. This is useful when you are for example dynamically adding new nodes after the layout has stopped. The graph.layout.reset() restarts the layout from scratch.
graph.layout.refresh()
graph.layout.reset()
When using the spring-force layout, graph.layout has a tweak() method that allows you to play around with the internals of the layout algorithm:
graph.layout.tweak(k=2, m=0.01, w=15, d=0.5, r=15)
The k parameter is the force constant by which nodes are pushed away from each other, m is a dampener for the total attractive/repulsive force, w is a weight multiplier (so heavier edges have a bigger attraction), d is the maximum node movement per iterations and r is the radius of repulsive force originating from each node.
You may find the following layout properties easier to use:
If you are using the circle layout, graph.layout has only one property:
You can customize the look and feel of the graph down to the bottom. The graph.styles dictionary has different styles for different nodes. Each style has some color and font properties and a range of methods for drawing each element in the graph. The styles dictionary is accompanied by a styleguide containing rules that define how and when to apply the styles. You can easily modify existing styles, create new ones, and devise your own rules for how to apply them.
Predefined styles
Let’s have a look at the different styles in a graph:
| default: this style is used for nodes that have no style defined. Edges will always use the default stroke color. | |
| light: a style with subtly highlighted nodes. By default it is used for nodes directly connected to the root. | |
| back: a style with green colored nodes and curved edges.  By default it is used to indicate peers of the root node. | |
| dark: a style with blue colored nodes. By default it is used to indicate nodes with four or more connections. | |
| important: a style with big blue colored nodes that get an extra outline. By default it is used for nodes that have a weight of 0.75 or more. | |
| highlight: a style that marks paths in pink. By default it is used to indicate the highlight path supplied to graph.draw(). | |
| root: a style that marks the root node in the graph. |
print graph.styles.keys() >>> ['default', 'light', 'back', 'marked', 'dark', >>> 'important', 'highlight', 'root']
You can change the properties of each of the individual style objects:
graph.styles.root.fontsize = 20
Or set a property on all styles:
graph.styles.stroke = color(1)
Here’s an example of how to add your own custom style:
s = g.styles.create("red") s.fill = color(1, 0, 0.25, 0.75)
Style properties
A style object has the following properties:
Styleguide
You can assign the name of a style to node.style and then when the network is drawn the node will be visualized using the style’s properties and drawing methods.
You can assign styles by hand - for example, here’s how to make all nodes with a weight of more than 0.6 ‘important’:
for node in graph.nodes: if node.weight > 0.6: node.style = "important"
Rules like these (’heavy nodes are important’) can also be bundled in the styleguide dictionary:
graph.styles.guide.append("important", lambda graph, node: node.weight > 0.6)
The default rules in the guide are:
{ "light" : lambda graph, node: graph.root in node.links "dark" : lambda graph, node: len(node.links) > 4 "important" : lambda graph, node: node.weight > 0.75 "root" : lambda graph, node: node == graph.root "back" : lambda graph, node: node == graph.events.clicked }
Below is another interesting rule that keeps clusters of nodes together. The edges of nodes
that have only one connection become shorter, all others become longer. The default styleguide
uses a simpler version.
def cluster(graph, node): if node == graph.nodes[0]: for e in graph.edges: e.length = 4.0 if len(node.links) == 1: graph.edge(node.id, node.links[0].id).length = 0.2 graph.styles.guide.append("cluster", cluster)
To apply the styling rules to the network:
graph.styles.apply()
There’s a graph.styles.guide.order property (which is a list of style names) that defines the sequence in which style rules will be applied. There’s also a graph.styles.clear() method to remove all the rules.
Style drawing methods
A style has customizable drawing methods. We will only go into this briefly here. Developers can check the source code in the style.py file in the library. Here’s a quick example of how we add our own custom patch for edges:
def curly_edge(style, path, edge, alpha=1.0): path.moveto(edge.node1.x, edge.node1.y) path.curveto( edge.node1.x - 40, edge.node1.y, edge.node2.x + 40, edge.node2.y, edge.node2.x, edge.node2.y, ) graph.styles.default.edge = curly_edge graph.draw() |
You can use very small graphs (<100 nodes) in an animation and watch them unfold fluidly. The graph object has functionality for mouse interaction as well, bundled in the graph.events object. It has the following properties:
|
When you hover over a node the graph.events.hover() method fires. It will try to display a description of the node’s id from WordNet (if you have the Linguistics or WordNet library installed). To display your own popup text for a given node, register it in the graph.events.popup_text dictionary: graph.events.popup_text["organism"] = "hello" In an animation you can also simply press down on a node and drag it around to where you want it. The graph will stabilize by itself.  This method takes one node parameter and does nothing by default, so if you want clicking behavior you’ll have to assign your own command: def click(node): print node.id+" clicked" graph.events.click = click |
Finding out if two nodes are connected (with zero or more other nodes in between them) is
easy enough with the node.can_reach() method, which returns either True or
False:
node.can_reach(node, traversable: lambda node, edge: True)
What is intriguing about this method is the optional traversable parameter. You can pass it a custom command. This command takes two parameters, a node and an edge, and returns True if the given node is allowed to travel over the given edge.
This allows for more elaborate searches. For example, in the Perception library all edges have a type, like is-part-of or is-related-to. Traversables are used to check if two nodes are connected using only specific types of edges: an oak is a tree only if the oak node can reach the tree node using only is-a edges (and not, for example, is-property-of).
Graphs are not only useful to visualize data, but to analyze it as well. Knowing what the shortest path is, how to get from one node to another, can tell us something of how those nodes relate to each other.
Dijkstra’s shortest path algorithm is a way to find the closest route from one node to another in the network. For example, if the nodes in the network represent cities and their strength represent driving distances between pairs of cities connected by a direct road, Dijkstra’s algorithm can be used to find the shortest route between two cities.
graph.shortest_path(id1, id2, heuristic=None, directed=False)
The graph.shortest_path() method returns a list of node id’s connecting the two nodes with the given id’s. If no connection can be found it will return None.
path = graph.shortest_path(119, 381) graph.draw(highlight=path, weighted=True) print path >>> [119, 383, 478, 78, 381]
When searching for a shortest route the edge weight becomes important. Edges with a higher weight represent shorter routes. You can think of an edge with a weight of 1.0 as a highway and an edge with a weight of 0.0 as a mountain trail. So even if an edge looks longer onscreen (because it yields a nicer layout for example) it might still be a better candidate to travel by. Likewise, a straight connection may be abandoned in favor of a detour on heavier edges.
Optionally you can also supply your own heuristic function to tweak the pathfinder. It is
a command that takes two node id’s as its parameters and returns a number (usually between -1
and +1). The lower this number gets the more interesting the connection between the two
nodes becomes. For example, in a game environment you could use edge weight to represent the
quality of a road through the world, and supply heuristic terrain penalties for mountains,
swamps, oceans - to discourage AI-controlled characters from trying to cross the ocean or walk
through walls to reach an enemy.
Centrality
How a node is connected to other nodes influences its importance in the network. The Graph library uses two measurements to determine a node’s importance: betweenness centrality and eigenvector centrality.
|
|
Consider a node that has eight connections to other nodes. Consider another node that has three connections that each connect to two other nodes. An initial naive estimate would be to say that the node in the first case is more important because it has eight connections. However, the node in the second case has the potential to influence up to nine other nodes, and therefore it has a higher importance in the network. The king of a country has only his advisors as direct connections, but his influence is obviously much higher than a post office secretary in the same country who may have hundreds of direct connections with his clients. Eigenvalue centrality is what Google’s PageRank algorithm uses to rank web pages. Read some more interesting details on the 20bits blog. |
The graph has two methods that return a list of nodes sorted according to traffic or weight:
graph.nodes_by_traffic(threshold=0.0)
graph.nodes_by_weight(threshold=0.0)
If you dynamically add new nodes to the graph the balance can shift and you may want to recalculate the proximity values:
graph.betweenness_centrality(directed=False)
graph.eigenvector_centrality(reversed=True, rating={}, start=None, iterations=100, tolerance=0.0001)
Both methods recalculate a node’s traffic/weight property and return a dictionary of node id’s linked to a value between 0.0 and 1.0. You may also notice the optional rating parameter which is a dictionary of node id’s linked to a score to influence it’s weight (e.g. Google not only examines a web page’s connections but also its contents - the score of a page’s content could be reflected in the ranking dictionary).
Clustering means the classification of objects into different groups, so that all the objects in a group share some common traits (e.g. a rabbit and a bird both belong to the animal group). Clustering is in part related to how you organize your graph, and in part to what analysis you can then perform on the graph. The Graph library has some simple tools for cluster analysis.
graph.nodes_by_category(name)
The graph.nodes_by_category() method returns a list of all nodes that have their category property equal to the given name.
graph.fringe(depth=2)
The graph.fringe() method returns a list of nodes on the perimeter of the graph. With a depth of 1 it returns all the leaf nodes, with a depth of 2 all the leaf nodes and nodes connected to leaf nodes, etc.
graph.sub(id, distance=1)
The graph.sub() method returns a new graph object that is a subset of the
given graph. If distance is 0, it will contain only the node with the given id.
If distance is 1, it will contain the node and all nodes directly connected to that node. If
distance is 2, it will also contain all nodes that are connected to nodes directly
connected to the given node, and so on. You can also supply a list of id’s instead of a single
id.
Yet another way to create a subgraph is to pass a filtering function instead of an id. For example:
graph = ximport("graph") g = graph.create(iterations=500, distance=0.8) g.add_node("PlotDevice") g.add_node("Linguistics", category="library") g.add_node("WordNet", category="library") g.add_edge("Linguistics", "PlotDevice", label="related-to") g.add_edge("WordNet", "PlotDevice", label="related-to") g.add_edge("WordNet", "Linguistics", label="part-of") # subgraph containing only library nodes: g = g.sub(lambda node: node.category == "library", distance=0) g.distance = 1.4 g.solve() g.draw(directed=True)
Note: remember that if you want to draw a subgraph, you need to recalculate the layout with the update() or solve() method.
Subgraph set theory
Set theory deals with union, difference and intersection operations between sets of elements. You can compare subgraphs to find out which nodes they have in common (intersection), which nodes they do not have in common (difference) or which is the combined set of both subgraphs (union).
The following methods will return a new subgraph based on set operations:
graph1.join(graph2) # union, graph1 | graph2 also works
graph1.subtract(graph2) # difference, graph1 - graph2 also works
graph1.intersect(graph2) # intersection, graph1 & graphs2 also works
Cliques
In graph theory, a clique is a graph in which each node is connected to all the other nodes. There’s a graph.is_clique property that returns True when the graph is complete. Since each node is connected to every other node in a complete graph, its density will be 1.0.
graph.clique(id, distance=0)
graph.cliques(id, threshold=3, distance=0)
The graph.clique() method returns a subgraph of the biggest clique around the node with the given id. It takes an optional distance parameter which will also include other nodes connected to the nodes in the clique (see the distance parameter for the graph.sub() method).
The graph.cliques() method returns a list of subgraphs that are cliques of at least threshold nodes.
Partitioning
Finally, there’s a powerful technique to split a graph into its unconnected subgraphs. Sometimes your graph may contain two or more clusters of nodes without connections between them (especially if you don’t know where the data came from). The graph.split() method will return a list of unconnected subgraphs, sorted biggest-first:
subgraphs = graph.split() subgraphs[0].solve() subgraphs[0].draw()
Exporting a graph as a PDF may crash PlotDevice on some systems.
Disabling dropshadow and gradient effects should remedy this:
g = graph.create(depth=False)