Report 6 Stories
Report last updated: 2020-09-10
6.1 Rumi Ahmed
6.1.1 April 7, 2020 (via Facebook)
I lived through the swine flu (2009 H1N1) pandemic which infected 60 million (1 in 6 American) and killed about 12000 Americans. Global death toll was around 300000.
Then we lived through Bird Flu (50% mortality), Ebola (70% mortality), MERS(40% mortality), Zika (airborne and. It this defect) scare and cattle call.
So when COVID-19 started ravaging Wuhan, China and Lombardy, Italy - me and many of my frontline, more informed physician colleague were like the mythical shepherd boys. We Have been dismissive!
Dismissive because, with R0 of 2.5-2.9, SARS-COV-2 was less contagious than SARS-1 of 2002 and definitely much less fatal than SARS-1, MERS, Bird Flu, Ebola etc. We knew that SARS-1, MERS, Avian influenza blazed for a few months in a few localities then stoped abruptly. R0 became <1, the epidemic died down.
And SARS-COV-2 was a petty coronavirus! It was a mere coronavirus!! It was not the feared shifted- drifted influenza virus causing Flu pandemic we have been fearing half of the last century.
Despite SARS -1 and MERS experience - we didn’t give this bat coronavirus due respects it deserved. It was not the feared white walker, it was not the novel influenza pandemic we always have been fearful about.
But this novel coronavirus SARA-COV-2 turned out to be the cause of first coronavirus pandemic, to be more precise , the first non-influenza pandemic in history of mankind.
So what went wrong with this Novel coronavirus? Biologically less contagious and less fatal than SARS-1, instead of behaving like SARS-1 or MERS, why this novel coronavirus is blazing like a catastrophic forest fire?
The answer is in one protein. Remember this name. It’s a protein called Exonuclease. Exonuclease!
We are still inside the deep fog of war, at the center of a bloody- muddy battle field, we are wielding swords blindly! We don’t have the clarity of a bird eye view or the luxury of a time lapse retrospect! Hazy view through early data says the following about this new enemy - this virus-
- It is a bat virus, and thorough perpetual mixing and mutation inside the bat reservoir, this bat virus mutated and developed as a new virus sometimes between 1948 and 1972. Chinese horseshoe bats are carrying this virus for the last several decades!
- Like tornado chasers - there are a group of scientists knows as virus chasers who are skimming wild bat habitants in search of viruses that they call pre-pandemic viruses. They are isolating bat viruses which in the future has the potential to transmit to human and cause a new pandemic. They are pre-preparing for the next pandemic by sequencing them and trying to see vaccine potential. This new SARS-COV-2 was not in that pre-pandemic bat virus database. In fact this virus was never known to us despite it was circulating inside horseshoe bats for the last several decades. It says that our limited search efforts with lackluster funding was not enough to capture many bat viruses.
- This horseshoe Chinese cave bats are not fruit bats- they have teeth and may infect human / other animals by any close contact.
- Somehow humans got this SARS-COV-2 bat virus and stated getting sick. Did this jump ( virus changing host from bat to human) happen last fall? Did similar COVID-19 disease clusters happen before 2019 but we didn’t notice? Very possible.
- Remember AIDS. We always thought that HIV virus came to Human from Chimpanzee in 1983. But we now know that the jump probably happened in 1929! Since 1929, there have been undetected local epidemics AIDS.
- So SARS-COV-2 virus found this new host in human species which is abundant in planet earth.
- This virus, in this new host, has only one job in life- propagate!
- Remember the evolutionary theory of selection. This virus came this far- and so far winning against the most powerful species ever lived in this planet, Homo sapiens - this virus is the fittest. Genetically and biochemically, this virus is the chosen one, the selected one to survive and propagate. Millions / billions of other weaker viral species got defeated / lost out - this one didn’t! This is pure simple theory of selection!
Why this virus has been selected to come this far and win over a complex new host? There are many factors and explanations! But one factor is that it has a protein called Exonuclease in its arsenal!
Exonuclease is a protein this virus generates for a job called genetic proof-reading! Viruses are constantly replicating into new viruses. That’s how they propagate. Usually viral spreads die down after an initially blaze because the progeny keeps getting weaker and weaker due to constant mutations. Usually viruses don’t have a quality control officer in its payroll!
But this virus has a powerful quality control officer. This Exonuclease protein is ensuring that every single progeny this virus is producing is a healthy progeny. It’s not allowing heavily mutated viruses which usually terminated the chain of transmission. And because of this Exonuclease, unlike SARS-1, MERS, this virus is not suddenly disappearing from the horizon; rather with Alexander the Great vigor, this virus is marching - conquering country after country, sacking city after city!
6.1.2 April 16, 2020 - Bats (via Facebook)
Of bats and viruses!
Part -1 Bats.
I am jealous of bats.
Bat is a mammal, I am also a mammal; and I am definitely a bigger mammal. I can’t fly while bats can! But I am jealous of bats not only because bats can fly I can’t!
There are many more thing about bats that makes us look at this species of mammals with awe! Although we don’t have a clear bat census - bats, as well as rodents, are the two mammals who probably outnumber humans. Of all the mammals in this planet, 20% are bats.
We humans are children compared to bats physical capability. A bat flies 5-6 hours nonstop nightly. Their maneuvering capacity is even better than birds. When bats fly they can increase their metabolism so high that their heart beats over one thousand times a minute. Compared to that if our heart beats 300 times a minute for a few minute - it stops!
During flying bats body temperature peaks as high as 108F / 42C. A bat body can easily tolerate that high temperature. If that happened in human - the brain would have been fried leading to seizure!
To process all that much metabolism, bats have a pair of super kidneys that’s like 20 pair of human kidneys to remove all these metabolites!
Bats immune system is another nature’s wonder. If bat’s immune system is equivalent to Windows 10, our immune system may be like MS DOS!
Each Bat can carry over hundred types of viruses. Several types of coronavirus including SARS, MERS and current SARS - COV-2 live in bats, as do much more dangerous viruses like Rabies, Ebola, Nipah, Hendra!
See we are doing hand hygiene, social distancing - still we are struggling to safeguard ourselves from virus. Bats neither do hand hygiene nor they follow social distancing as they live in a crowded group setting.
Bat’s immune system can seamlessly handle these viruses for ages, live together not harming each other. But if human gets one of these viruses, they either gets totally defeated in first attack or launch such an erratic immune response - it kills itself by its own action! And exactly the same thing we are seeing in coronavirus pandemic these days!
Bat, as well as rodents are major reservoir of viruses and probably are the source of our current pandemic and probably a more deadly pandemic in the future.
Including three new, there are seven coronavirus in humans. Of these seven, it seems at least six came from to us from bats. Coronavirus 229E jumped from bat to human in ancient times. While the SARS-COV-2 possibly jumped sometime last November!
One human cold coronavirus - HKU3 - it is probably the only one that came to us from cows! It probably happened about a hundred years ago. Although we don’t have a official record - scientists have some evidence that coronavirus HKU3 possibly caused serious illness when first jumped to humans!
If we take history as an indicator for the future - it is more likely that the next COVID-19 crisis will start with another virus from bat.
That’s why our human race will have to invest a lot of our resources in learning more about bats and the viruses that reside in them and the interactions between them!
 But we’ll never be certain about it unless until some day we’ll be able to collect, culture and isolate this virus in a bat.
That’s what Dr. Linfa Wang did. SARS outbreak happened in 2002-2003. We had a genetic sequence suggesting it’s bat origin. But that was not enough. We have to find it in a bat! Dr. Linfa wang of Duke Global Health Institute at Duke National University of Singapore did exactly that thing. He spent ten years time searching / crawling / climbing cave to cave in remote rural China. He would collect bat droplet and real bat sample swab and look for a genetic match! And after ten years search he finally found the SARS virus in a bat!
We talked about the bat lady Dr Shi Zheng-Li of Wuhan institution of Virology that day . She is doing the same thing. As are two agencies in USA, PREDICT -1 and PREDICT -2. Unbeknownst to all of us -there is an active search for bat viruses, the virus that can attack us at some point in future!
— In the second part I’ll discuss more about the viruses. Stay tuned! Part 2 will be about viruses!
6.1.3 April 21, 2020 - Bats (Part 2 and 3)
Talking about viruses means throwing in a lot of large mathematical values and big numbers - the extent of which most of our minds are unable to fathom.
We know quiet a bit about people being infected with coronavirus. We we also see that while some are becoming sick, a lot more who are invaded / infected by the virus but are not getting sick.
 Killing the new host is not in the best interest for ￼the virus also. These virus are here today after 3 million years of evolution and selection. And they are genetically and proteomically fittest, hence very apt at surviving and spreading in current zoonome.
Only thing they want is to make our body their home and live without harming us much. We are great hosts for them - because there are seven billion of us and we live a social life - in close congregation - so if needed they can jump from one to another. We are their dream home!
Once they can safely reside in us - we are so many in number - they won’t have to look for new home- their only job will be to keep propagating - for millions of years!
Naturally and understandably, our body is home to innumerable viruses. A good count or number is impossible to deduct. We have 40 trillion bacteria in our body and usually we know that there are ten times more viruses in nature than bacteria. Hence it is assumed that there are 400 trillion viruses who call out body their home.
We have a peace treaty with these viruses, there is a longstanding ceasefire. We don’t fight each other. Many, if not most, viruses are helpful for us.
But how can a virus be helpful? Before we discuss that let’s first talk about virus biodiversity in our body. We are still learning and our knowledge of human virome is still very incomplete.
So far what we have identified - there are 53 different types of human viruses in our body and about 53000 types of viruses which are the viruses living inside the bacteria that live inside our body. We know this from gene sequencing study - really isolating them in culture has been an impossible job.
Those viruses in bacteria keeps bacteria population in our body under check and don’t let bacteria overwhelm us/ take over us!
Humans are mammals. Roughly there are about 6000 species of mammals. How many virus species each mammal carry? So far there has been one real study. A big group of scientists led by world top emerging infection scientist - Dr. Ian Lipkin went to Bangladesh - randomly selected a site - collected flying fox ( fruit bats) for throat swabs, collected urine and stool specimen. A total of -1800 samples! On average they found 58 viruses per bat. Almost all the viruses they identified were new to us. They isolated few bat coronaviruses and most other types of knows virus types. Based on that model we think that mammals have about 400000 different types of viruses, the number rises to 100 million types of we count all vertebrates!
But our land based virus is nothing compared to the viruses found in our oceans. Canadian virologist Curtis Suttle always use colorful / sensational allegories when he tries to describe the amount of viruses that reside in our ocean waters.
There are 10 to the power 30 number of viruses in our oceans. What does the number 10 to the power 30 mean? It’s a number that normal human brain like mine can’t process. Let me try to explain- if we line up all these marine viruses (100 micron in length on average) side by side that will stretch 10 to the power 28 Kilometers. Believe me that’s a very long distance - about 100 million light years long! Our galaxy is about 150,000 light years across! This line of viruses will span 60 galaxies! How far is the closest star system from earth? Proxima Centauri it is and it’s only about 4.2 light years away!!
How much all these ocean virus weight? Their collective weight is equal to the weight of 75 million blue whales!
About 10 to power 23 infections are happening every second in our oceans! Virus is the major determinant in the delicate echo balance and marine life cycle and are responsible of 50 % of planet’s oxygen production!
In every liter of coastal water there are 10 million viruses. Overall in oceans there are 10 million times more viruses than stars in the galaxy!
So that’s about water / sea / river! What about the sky?
Well, about 9000 feet above ground, in the sphere called troposphere, there is transcontinental air current above our weather system! Billions of viral and bacterial particles fly all the way to that high and do transcontinental travel for thousands of miles! And then they shower on us in billions! A single square meter of the planet’s surface could be showered with hundreds of millions of viruses — and tens of millions of bacteria — in a single day. These viruses are all over in the air around us. Luckily they are not the types of viruses that are pathogenic to us! Most can’t enter our cells!
Measles is a type of virus that may remain air suspended and travel to the far corner of the room staying suspended in air and may infect everyone breathing that air. So are Zoaster! They can fly in air and infect people. As far as we known the current SARS-COV-2 doesn’t have that ability! Luckily Most virus doesn’t have that capacity.
Viruses need receptors/ window or door in the cell to enter the cell. Without that they can’t enter. Once virus enters cells - it depends on the Virus how long it will take to start the symptom. Influenza virus symptom starts only on one to two days day after infection! On the other had it may take AIDS virus upto 18 years to start the symptoms!
Typically thousands or tens of thousands of coronaviruses need to enter the cells of nose / throats of a person to infect him/ her! But that number is nothing because a hundred million coronavirus particles could fit on the head of a pin. And although we read, worry, talk, discuss about how many days this virus can stay alive on what surface, we need to know that infection window is highest in the first ten minutes.


glow.widgets.Slider examples
Basic Slider
With ticks, snaps and labels.
Slider Value:
Vertical Slider
With dark theme.
Slider Value:


QA Academy Graduation
Click on image
prev
next
QA Academy Graduation
Joro in the State
WordCamp Sofia 2013
Software Academy Graduation 2013


Overview
The goal of this style guide is to provide a flexible framework for all Data Team graphic projects. This wiki should act as a reference. However, the style guide repo also provides a suite of style files that can be installed via NPM and utilized as a boilerplate styling framework for your projects.
This repo comes with versioning and is installable via npm.
Inspiration is pulled liberally from the SF Chronicle and Texas Tribune news app templates.
Installing the style files
npm install --save-dev express-news-styleguide
Utilizing the style files
The style files are written in SCSS — a Sass syntax that builds on the existing CSS syntax. If you're unfamiliar with Sass or SCSS, read this guide to catch up on the basics.
On its first iteration, the style files are broken into two folders – base and theme. Currently theme contains just one file, graphic.scss, which operates as a boilerplate that can be used with c3 and graphicBuilder graphics. Learn more about how base is structured here.
If installing via NPM, you can access the style files in your project's .scss files like this:
@import 'node_modules/express-news-styleguide/init-base';
@import 'node_modules/express-news-styleguide/theme/graphic';
Typography
The most important rule to remember with typography is that, in graphics, we use a sans-serif font. This includes for the header, the chatter and anywhere else in the graphic. Since our regular text is serif, this allows us to differentiate graphic blocks and copy from regular text and headers.
With this in mind, we generally utilize three fonts. These are as follows:
- Sans-serif (for use in all graphic typography):
"Helvetica Neue", Helvetica, Arial, sans-serif;
- This is some text written with our main sans-serif font.
- Serif (for use in regular paragraph text outside of graphics):
"Sanchez", serif;
- This is some text written with our main serif font. We use this for paragraph text in stories but not graphics.
- Serif (for use in titles outside of graphics):
"Suez One", serif;
- This is some text written with our title serif font. We use this for title in stories but not graphics.
Two of those fonts will need to be imported from Google Fonts. That can be done in two ways:
- In HTML:
<link href="https://fonts.googleapis.com/css?family=Sanchez|Suez+One" rel="stylesheet">
- Or in CSS:
@import url('https://fonts.googleapis.com/css?family=Sanchez|Suez+One');
Font sizes are flexible at the moment. However, if we assume the baseline font size to be 14px
, we can say that in most cases:
- Paragraph text should be
1.2em
- Title text should be
2em
Graphic color schemes
At least for the moment, we haven't set any definitive styles for graphic colors. That being said, we do have a graphic color chart that you can use to help pick logical color combinations. It looks like this:
You can download the graphic color chart (and view it in more detail with hex and RGB codes) by clicking here.
We also support the use of ColorBrewer color schemes.
Political colors
When 'tis the season, here are the colors to use:
- Democratic Blue:
rgb(23, 117, 174)
#1775AE
$dem-blue // sass variable
- Republican Red:
rgb(214, 73, 70)
#D64946
$rep-red // sass variable
Standard ExpressNews colors
Colors should match those utilized in the story template and/or those in your graphic depending on proximity. This being said, there are two colors we use frequently on E-N.com:
- ExpressNews Black:
rgb(20, 20, 20)
#141414
$en-black // sass variable
- ExpressNews Red (utilized for linked text):
rgb(186, 20, 26)
#BA141A
$en-red // sass variable
Longform Colors
The longform React template comes with its own unique color scheme. For reference, here are the colors associated with that template:
- Longform Red:
rgb(246, 0, 0)
#F60000
$longform-red // sass variable
- Longform Yellow:
rgb(248, 248, 0)
#F8F800
$longform-yellow // sass variable
- Longform Orange:
rgb(252, 176, 1)
#FCB001
$longform-orange // sass variable
- Longform Gray:
rgb(122, 122, 122)
#7A7A7A
$longform-gray // sass variable
Understand the SASS variables
Each color discussed above, including all those in the graphic color chart, is available as a SASS variables in the ExpressNews style guide. If you download this style guide via NPM, you can utilize the variables in your project and modify them as you see fit for the circumstance.
If you are new to SASS, you can learn more here.
Understand The Base .SCSS Files
Everything you need to jump start a project is contained in the base folder. Here's an explanation of each of the partials:
_base.scss
These are the only styles applied directly to HTML elements. If you really need a clean slate, don't use this partial. But it's helpful for normalizing styles and inheriting basic news apps prose styles without using additional classes.
_colors.scss:
All of our colors are assigned to $variables, most of which have a descriptive name to help you decide when to use it. For example, $rep-red and $dem-blue are used for typical political party designations.
_tables.scss:
This partial contains one mixin to rule them all — i.e. all the variations of mobile table styles. Skip to Tables to learn more.
_typography.scss:
Our style guide has a modular typography system. By changing the size $variables, you can change font-sizes across the entire project. The system also allows you to designate font-size with .classes in your HTML or @extend %font-sizes on new classes.
Tables
I will need to build out proper examples of how to use the table styling, but I think it will really help to speed up our efforts in building flexible mobile first tables. The style file is viewable here.


Project points in data
onto the globe and filter data
to points within the current field of view.
do_projection(data, id, lon = 0, lat = 0, n.period = 360, n.frames = n.period, keep = FALSE)
| data | a data frame. |
|---|---|
| id | character, column name referring to column of |
| lon | starting longitude for rotation sequence or vector of arbitrary longitude sequence. |
| lat | fixed latitude or vector of arbitrary latitude sequence. |
| n.period | intended length of the period. |
| n.frames | intended number of frames in animation. |
| keep, | if |
returns a data frame containing visible points on the globe or all points along with a boolean inview
column.
do_projection
projects the coordinates in data
onto the globe and filters data
to the subset of rows
containing data which are visible given the current field of view.
The field of view is defined by the centroid focus latitude and longitude pair in the sequence of latitudes and longitudes whose index
corresponds to the frame ID in data
. data
may containing rows with multiple unique frame ID values,
which the function will group the data by.
These values are used to determine position in the user-defined lon/lat sequence and the corresponding in-view subset of data
for each subset of data
grouped by the `id` variable.
library(dplyr) library(purrr) data(annualtemps) temps <- mutate(annualtemps, frameID = Year - min(Year) + 1) do_projection(temps, id="frameID")#>#> # A tibble: 28,641 x 5 #> lon lat Year z frameID #> <dbl> <dbl> <int> <dbl> <dbl> #> 1 -90 0.333 2010 0.33 1 #> 2 -90 13.7 2010 0.69 1 #> 3 -90 20.3 2010 0.54 1 #> 4 -90 27.0 2010 1.1 1 #> 5 -90 33.7 2010 1.35 1 #> 6 -90 40.3 2010 1.49 1 #> 7 -90 47.0 2010 1.24 1 #> 8 -90 53.7 2010 0.79 1 #> 9 -90 60.3 2010 1.4 1 #> 10 -90 67.0 2010 1.96 1 #> # ... with 28,631 more rowsdo_projection(temps, id="frameID", keep=TRUE)#>#> # A tibble: 55,080 x 6 #> lon lat Year z frameID inview #> <dbl> <dbl> <int> <dbl> <dbl> <lgl> #> 1 -177. 53.7 2010 1.09 1 FALSE #> 2 -177. 67.0 2010 3.21 1 FALSE #> 3 -177. 73.7 2010 2.76 1 FALSE #> 4 -170 53.7 2010 0.91 1 FALSE #> 5 -170 60.3 2010 2.47 1 FALSE #> 6 -170 67.0 2010 2.73 1 FALSE #> 7 -163. 20.3 2010 0.19 1 FALSE #> 8 -163. 53.7 2010 0.79 1 FALSE #> 9 -163. 60.3 2010 1.43 1 FALSE #> 10 -163. 67.0 2010 1.28 1 FALSE #> # ... with 55,070 more rows


Welcome to stk
’s documentation!¶
GitHub: https://www.github.com/lukasturcani/stk
Slack: https://t.co/LCPzWhvsVO
Overview¶
stk
is a Python library for building, manipulating, analyzing and
automatic design of molecules, including a genetic algorithm.
For quick navigation through the modules use Module Index. For a closer look at the genetic algorithm, start with Automated Molecular Design with Genetic Algorithms.
Basic Examples¶
Linear Polymer¶
The core function of stk
is to assemble molecules. Here is an example
of how a simple, linear polymer can be built. Starting with three monomers,
such as
each can be loaded into a StructUnit2
object from a molecular
structure file:
monomer1 = StructUnit2('monomer1.mol', 'bromine')
monomer2 = StructUnit2('monomer2.mol', 'bromine')
monomer3 = StructUnit2('monomer3.mol', 'bromine')
The first argument is the path to the structure file and the second argument specifies the functional group of the monomer.
To assemble a polymer only a single line of code is required:
polymer = Polymer([monomer1, monomer2, monomer3], Linear('ABC', [0, 1, 0.5], n=3))
Simply create a Polymer
object by giving it a list of
monomers and a topology object, in this
case Linear
. The topology object defines the the structure of
the polymer being assembled. The repeating unit is 'ABC'
, the orientation
of the each monomer along the chain is parallel, anti-parallel and random, respectively, and
the number of repeating units is 3
.
The assembled polymer can be written to a file
polymer.write('polymer.mol')
and will look like this.
Notice that the functional group has disappeared and been replaced by
new bonds between the monomers. The new bonds seem a little stretched,
so we can optimize the structure using an optimization function defined in
optimization
, in this case rdkit_ETKDG()
rdkit_ETKDG(polymer)
Again, the polymer can be written to a file
polymer.write('polymer_opt.mol')
and viewed
stk
also allows you to save the Python objects themselves in the JSON
format.
polymer.dump('polymer.json')
This allows you to restore a Molecule
object from a previous session.
polymer = Molecule.load('polymer.json')
polymer # < Polymer NOT Molecule object >
Molecule.load()
allows you to load any dumped stk
JSON object
regardless of its class and it will returned an object of the correct
class to you.
Molecular Cages¶
Molecular cages are relatively exotic molecules that look like, yes, cages. Here is an example:
Despite their apparent complexity, assembling a molecular cage is extremely straightforward. In fact, it is done in exactly the same way as a polymer.
First we define the building blocks of the cage:
bb1 = StructUnit2('bb1.mol', 'amine')
bb2 = StructUnit3('bb2.mol', 'aldehyde')
Here is what they look like:
Notice a slight difference, while the first building building block still
uses the class StructUnit2
, the second uses the class
StructUnit3
. The reason is that the first building block has
2 functional groups while the second has 3 functional groups. Each class
defines a slightly different set of operations for manipulating the
positions of the building blocks when assembling the cage. This is
important so that the building blocks are placed exactly how we want them
when constructing a molecule. However, all of this happens behind the scenes
and a cage can be constructed through a simple one-liner:
cage = Cage([bb1, bb2], FourPlusSix())
Notice that this is exactly the same as the polymer example. To generate
a cage, we simply create a Cage
object. We initialize it with
a list of building blocks and provide a topology instance, in this case
FourPlusSix
. Unlike the Linear
class, the FourPlusSix
does not require any additional arguments. Our assembled cage looks like
this
If we want to create a cage with a different topology but using the same building blocks, we provide a different topology instance:
cage2 = Cage([bb1, bb2], EightPlusTwelve())
The assembled cage looks like a cube:
Notice that the building blocks are the same, only the shape has changed. This is because a different topology instance was provided during initialization.
Here is a third example:
cage3 = Cage([bb1, bb2], Dodecahedron())
While we assembled some cages, the constructed structures are not particularly realistic. We can optimize the geometry using an optimization function:
macromodel_opt(cage, '/opt/schrodinger2017-4')
macromodel_opt(cage2, '/opt/schrodinger2017-4')
macromodel_opt(cage3, '/opt/schrodinger2017-4')
In this case the function macromodel_opt()
was used. We could have
used rdkit_ETKDG()
again but chances are the structures would
have been optimized quite poorly. The macromodel_opt()
function
requires a valid MacroModel
installation with a working license.
The argument '/opt/schrodinger2017-4'
is the path to the installation.
Note that there are many more cage topologies available (14+), which
can be found by looking in stk.molecular.topologies.cage
.
The topologies are organized into submodules based on the building blocks
required to build them. For example, all topologies in the
stk.molecular.topologies.cage.two_plus_three
submodule are composed of two and three functionalized building
blocks, all cages in the stk.molecular.topologies.cage.two_plus_four
submodule are composed of two and
four functionalized building blocks, cages in stk.molecular.topologies.cage.three_plus_three
are composed
of three functionalized building blocks and so on.
All cage topologies also support being built from more than two building blocks, to produce mixed or multi-component cages.
In addition, cage topologies support a number of optional arguments which allow the many possible structural isomers to be easily assembled. These topics are discussed in Advanced Cage Building.
Covalent Organic Frameworks¶
Just like the other molecules, covalent organic frameworks (COFs) are easy to construct:
bb1 = StructUnit2('cof_bb1.mol', 'amine')
bb2 = StructUnit3('cof_bb2.mol', 'aldehyde'))
cof = Periodic([bb1, bb2], Honeycomb())
Where the buliding blocks are:
The same pattern is used. First building blocks objects are created using
StructUnit3
instances. Then a molecule is assembled by creating
an instance of its class, in this case Periodic
. The molecule
being assembled is provided with the building blocks and the topology,
in this case Honeycomb
.
Because COFs are periodic structures, if we want to make a finite size molecule we have to create an “island”:
cof.island([5, 5, 1])
Here we created create a 5 by 5 by 1 grid of the periodic unit cell. This is a cut-out of our structure:
Other COF topologies are available in topologies.cof
. For example:
stk
also gives tools to build a large number of structural isomers
of each COF. This is done analogously to the organic cage case so reading
Advanced Cage Building is recommended.
Other Materials¶
stk
is a work in progress and currently supports only the above classes
of materials out of the box. However, stk
was designed to be easy
extend to other classes of molecules.
For a guide on how this can be done
see, Extending stk.
Other Features¶
Calculating Molecular Properties¶
stk
provides a variety of methods to calculate molecular properties.
What methods can be used depends on what kind of molecule object is created.
All molecules can use methods defined in Molecule
. All
building blocks can use methods in StructUnit
in addition to this.
Assembled molecules can use additional methods provided by MacroMolecule
.
Here are some examples:
# Calculate the energy of a molecule using rdkit and the UFF force field.
mol.energy.rdkit('uff')
# Calculate the energy of a molecule using MacroModel. Using force field
# number 16 (OPLS3).
mol.energy.marcomodel(16, '/opt/schrodinger2017-4')
# Calculate the maximum diameter of of a molecule.
mol.max_diameter()
# Calculate the cavity size of a cage molecule.
cage.cavity_size()
# Calculate the mean RMSD between the building blocks original
# structure and their structure inside an assembled macromolecule.
macro_mol.bb_distortion()
# Get the center of mass of a molecule.
mol.center_of_mass()
# Get the atomic symbol of atom with id of 13.
mol.atom_symbol(13)
Something to note about energy calculations, is that each time you run the method, the result gets saved. For example,
mol.energy.values # {}
mol.energy.rdkit('uff') # Returns 16.05
mol.energy.values # {FunctionData('rdkit', forcefield='uff'): 16.501}
mol.energy.macromodel(forcefield=16,
macromodel_path='path/to/macromodel/dir') # Returns 200
mol.energy.values # {FunctionData('rdkit', forcefield='uff'): 16.501,
# FunctionData('macromodel', forcefield=16): 200}
This can come in handy if you do not want to repeat expensive calculations.
Geometric Manipulations¶
In addition to molecular property calculation, stk
provides tools to
rotate and translate molecules. These tools are particularly useful when
defining the assembly process of a new class of molecules.
# Change the position of a molecule.
mol.set_position([1, 2, 3])
# Get a matrix holding the position of every atom in the molecule.
mol.position_matrix()
# Use a matrix to set the position of every atom in the molecule.
mol.set_position_from_matrix(some_matrix)
# Rotate the molecule along by pi radians about the vector (1, 1, 3)
mol.rotate(np.pi, [1, 1, 2])
Dealing with Multiple Conformers¶
Every Molecule
, be it a StructUnit
or a MacroMolecule
supports multiple conformers. These are stored in the underlying
rdkit
object held in Molecule.mol
.
Adding a new conformer to a StructUnit
is simple
bb1 = StructUnit2('bb1_conf1.mol', 'amine') # Loads molecule into conformer 0.
bb1.update_from_mol('bb1_conf2.mol', conformer=1) # Load into conformer 1.
Lets take a look
Well, one is clearly better than the other. At least they are easy to recognize.
Lets try this with a another building block as well
bb2 = StructUnit3('bb2_conf1.mol', 'aldehyde')
bb2 = bb2.update_from_mol('bb2_conf2.mol')
Also pretty distinguishable. This is good, it makes it easy to show
that you can pick which conformers to use for assembly with MacroMolecule
cage = Cage([bb1, bb2], FourPlusSix(), bb_conformers=[0, 0])
cage.add_conformer([0, 1])
cage.add_conformer([1, 0])
cage.add_conformer([1, 1])
These are the conformers we produced!
stk
will use whichever StructUnit
conformers you want, when
constructing conformers of the MacroMolecule
itself.
Most methods and functions in stk
also support conformers.
mol.position_matrix(conformer=1)
mol.energy.rdkit('uff', conformer=0)
mol.cavity_size(conformer=1)
# And so on ...
Dealing with Multiple Molecules¶
When batches of molecules are created, it is often desirable to optimize
them all at once. By placing the molecules in a Population
instance, all molecules can be optimized in parallel.
pop = Population(cage, cage2, cage3)
pop.optimize(FunctionData('macromodel_opt', macromodel_path='/opt/schrodinger2017-4'))
In addition to this, the Population
class provides some handy
tools to assemble large amounts of molecules at a time. For example if
we want to create every possible cage from a set of building blocks and
topologies:
bbs1 = [StructUnit2(path, 'aldehyde') for path in ('1.mol', '2.mol', '3.mol')]
bbs2 = [StructUnit3(path, 'amine') for path in ('4.mol', '5.mol', '6.mol')]
# Create 18 Cage molecules.
pop2 = Population.init_all(Cage, [bbs1, bbs2], [FourPlusSix(), EightPlusTwelve()])
Or if we want to select building blocks at random and create 5 cages:
pop3 = Population.init_random(Cage, [bbs1, bbs2], [FourPlusSix(), EightPlusTwelve()], 5)
The population can also be used to calculate statistics across all molecules. For example, if you want to know the average cavity size of your cages:
pop.mean(lambda x: x.cavity_size())
Finally, we can use the population to write structure files of all the molecules to a folder
pop.write('dirname')
or we can dump the population to a JSON file
pop.dump('pop.json')
and recover the stk
objects later
pop.load('pop.json', Molecule.from_dict)
pop[0] # <StructUnit2 at 0x01283>
pop[1] # <Periodic at 0x12498>
Automated Molecular Design with Genetic Algorithms¶
Via the ga
module, stk
includes a genetic algorithm which
can be used to evolve molecules that fulfil user defined design criteria.
The genetic algorithm can be run from the command line using:
$ python -m stk.ga input_file.py
The input file is a simple python script which defines the mutation,
crossover, selection and other functions the genetic algorithm
should use. For details on how to build an input file see GAInput
and <no title>.
The genetic algorithm automatically works with any molecules that stk
can construct, just make sure you define an appropriate fitness function.
It will also work with StructUnit
if you do not wish to use
stk
’s construction capabilities.
Take for example the following input file which runs the GA on polymers and selects building blocks which have the most atoms.
# big_monomers.py
# ################################################################
# Import stuff.
# ################################################################
import stk
# ################################################################
# Number of CPU cores to use.
# ################################################################
processes = 1
# ################################################################
# Disable debug population dumps.
# ################################################################
pop_dumps = False
# ################################################################
# Population size.
# ################################################################
pop_size = 20
# ################################################################
# Number of generations to create.
# ################################################################
num_generations = 50
# ################################################################
# Number of mutation operations to perform each generation.
# ################################################################
num_mutations = 5
# ################################################################
# Number of crossover operations to perform each generation.
# ################################################################
num_crossovers = 3
# ################################################################
# Population initialization function.
# ################################################################
# First create the StructUnit objects of the monomers. In
# this simple example, they are simple hydro-carbon chains terminated
# with either two amine or two aldehyde functional groups.
amines = []
aldehydes = []
for i in range(1, 50):
# There are 2 different backbones, alkane, alkene.
backbones = ['C'*i, '='.join('C'*i)]
for backbone in backbones:
amine_smiles = 'N' + backbone + 'N'
amine_monomer = stk.StructUnit2.smiles_init(
smiles=amine_smiles,
functional_group='amine')
amines.append(amine_monomer)
aldehyde_smiles = 'O=C' + backbone + 'C=O'
aldehyde_monomer = stk.StructUnit2.smiles_init(
smiles=aldehyde_smiles,
functional_group='aldehyde')
aldehydes.append(aldehyde_monomer)
# List of the possible topologies the polymers can have. In this
# simple example a single topology will suffice.
polymer_topologies = [stk.Linear(repeating_unit='AB',
orientation=[0, 0],
n=1)]
# Finally, define the function which is called to create the
# initial GA population. The "NAME" key holds the name of an
# initialization function of the GAPopulation class. The remaining
# key-value pairs are additional parameters for that function.
# Default parameters can be specified if desired.
init_func = {'NAME': 'init_random',
'macromol_class': stk.Polymer,
'building_blocks': [amines, aldehydes],
'topologies': polymer_topologies}
# ################################################################
# Selection function for selecting the next generation.
# ################################################################
# The "NAME" key holds the name of a method in the Selection class.
# The remaining key-value pairs are additional parameters for that
# method. The "population" parameter is not specified and any
# default parameters can be specified if desired.
generational_select_func = {'NAME': 'stochastic_sampling',
'use_rank': True}
# ################################################################
# Selection function for selecting parents.
# ################################################################
# The "NAME" key holds the name of a method in the Selection class.
# The remaining key-value pairs are additional parameters for that
# method. The "population" parameter is not specified and any
# default parameters can be specified if desired.
crossover_select_func = {'NAME': 'crossover_roulette',
'truncation': 5}
# ################################################################
# Selection function for selecting molecules for mutation.
# ################################################################
# The "NAME" key holds the name of a method in the Selection class.
# The remaining key-value pairs are additional parameters for that
# method. The "population" parameter is not specified and any
# default parameters can be specified if desired.
mutation_select_func = {'NAME': 'stochastic_sampling',
'truncation': 3,
'duplicates': True}
# ################################################################
# Crossover functions.
# ################################################################
# In this example there only one crossover function will be used,
# but can use multiple if we add them into the list.
# The "NAME" key holds the name of a method in the Crossover class.
# The "macro_mol" parameters are not specified and any default
# parameters can be specified optionally. All other parameters
# must be specified as key-value pairs.
crossover_funcs = [{'NAME': 'genetic_recombination',
'key': lambda x: x.func_grp.name}]
# ################################################################
# Mutation functions.
# ################################################################
# The "NAME" key holds the name of a method in the Mutation class.
# The "macro_mol" parameter is not specified and any default
# parameters can be specified optionally. All other parameters
# must be specified as key-value pairs.
# mutation_func1 substitutes the amine building block in the
# molecule with one from the list "amines", defined earlier.
mutation_func1 = {'NAME': 'random_bb',
'mols': amines,
'key': lambda x: x.func_grp.name == 'amine'}
# mutation_func2 substitutes the aldehyde building block in the
# molecule with one from the list "aldehydes", defined earlier.
mutation_func2 = {'NAME': 'random_bb',
'mols': aldehydes,
'key': lambda x: x.func_grp.name == 'aldehyde'}
# Here we tell the GA which mutation functions we want to use.
mutation_funcs = [mutation_func1, mutation_func2]
# ################################################################
# Optimization function.
# ################################################################
# In this example, for the sake of speed, we will not optimize
# constructed polymers.
# The "NAME" key holds the name of a function
# defined in the optimization.py module. The "mol" parameter is
# not specified and any default parameters can be specified
# optionally. All other parameters must be specified as key-value
# pairs.
# Note that "do_not_optimize" is the name of a function
# in this module. It simply returns immediately and as a result does
# no work.
opt_func = {'NAME': 'do_not_optimize'}
# ################################################################
# Fitness function.
# ################################################################
# The "NAME" key holds the name of a function defined in the
# "fitness.py" module. The "macro_mol" parameter is not
# specified and any default parameters can be specified if desired.
# The remaining parameters must be specified as key-value pairs.
fitness_func = {'NAME': 'building_block_atoms'}
Running the genetic algorithm with this input file:
$ python -m stk.ga big_monomers.py
will produce the following directory structure:
|-- stk_ga_runs
| |-- 0
| | |-- counters
| | | |-- gen_1_crossover_counter.png
| | | |-- gen_1_mutation_counter.png
| | | |-- gen_1_selection_counter.png
| | | |-- ...
| | |
| | |-- final_pop
| | | |-- 150.mol
| | | |-- 2160.mol
| | | |-- 9471.mol
| | | |-- ...
| | |
| | |-- big_monomers.py
| | |-- database.json
| | |-- progress.json
| | |-- errors.log
| | |-- progress.log
| | |-- epp.png
| | |-- epp.csv
| | |-- output.tgz
A glance at the evolutionary progress plot in epp.png
will show us
how well our GA did.
Running the genetic algorithm again:
$ python -m stk.ga big_monomers.py
will add a second subfolder with the same structure:
|-- stk_ga_runs
| |-- 0
| | |-- counters
| | | |-- gen_1_crossover_counter.png
| | | |-- gen_1_mutation_counter.png
| | | |-- gen_1_selection_counter.png
| | | |-- ...
| | |
| | |-- final_pop
| | | |-- 150.mol
| | | |-- 2160.mol
| | | |-- 9471.mol
| | | |-- ...
| | |
| | |-- big_monomers.py
| | |-- database.json
| | |-- progress.json
| | |-- errors.log
| | |-- progress.log
| | |-- epp.png
| | |-- epp.csv
| | |-- output.tgz
|
| |-- 1
| | |-- counters
| | | |-- gen_1_crossover_counter.png
| | | |-- gen_1_mutation_counter.png
| | | |-- gen_1_selection_counter.png
| | | |-- ...
| | |
| | |-- final_pop
| | | |-- 41.mol
| | | |-- 221.mol
| | | |-- 1391.mol
| | | |-- ...
| | |
| | |-- big_monomers.py
| | |-- database.json
| | |-- progress.json
| | |-- errors.log
| | |-- progress.log
| | |-- epp.png
| | |-- epp.csv
| | |-- output.tgz
The genetic algorithm can also be run multiple times in a row:
$ python -m stk.ga -l 5 big_monomers.py
which will run the GA 5 separate times adding 5 more subfolders to the directory structure:
|-- stk_ga_runs
| |-- 0
| | |-- ...
| |
| |-- 1
| | |-- ...
| |
| |-- 2
| | |-- ...
| |
| |-- 3
| | |-- ...
| |
| |-- 4
| | |-- ...
| |
| |-- 5
| | |-- ...
| |
| |-- 6
|-- ...
The benefit of using the -l
option is that the molecular cache is
not reset between each run. This means that a molecule which was constructed,
optimized and had its fitness value calculated in the first run will
not need to be re-constructed, re-optimized or have fitness value
re-calculated in any of the subsequent runs. The cached version
of the molecule will be used.
However, the molecular cache be pre-loaded even when the -l
option is
not used. The input file allows the definition of a variable
databases
, for example
# some_inputfile.py
databases = ['path/to/some/population1.json',
'path/to/some/other/population2.json']
If this variable is defined in the input file, any molecules present in the population dump files will be loaded into the cache before the GA starts. This means that any molecules found in these populations will not be re-optimized, or have their fitness value re-calculated if discovered by the GA.
The output of a single GA consists of a number of files and
directories. The counter
directory holds .png
files showing
how frequently a member of the population was selected for mutation,
crossover and generational selection. For example, this is a
crossover counter
It shows that molecule 168
was selected twice for crossover, while molecules
60
, 170
, 167
, 63
and 153
were selected once. The
remaining molecules did not participate in crossover operations
in that generation.
If you do want want the GA to produce these files, simply tell the GA in the input file
# some_input_file.py
counters = False
The final_pop
directory holds the .mol
files holding the
structures of the last generation of molecules.
The file big_monomers.py
is a copy of the input file. The database.json
file is a population dump file which holds every molecule produced by
the GA during the run. This can be turned off with
# some_input_file.py
database_dump = False
progress.json
is also a population dump file. This population holds
every generation of the GA as a subpopulation. This is quite useful
if you want to analyse the output of the GA generation-wise. It
can be turned off with
# some_input_file.py
progress_dump = False
errors.log
is a file which contains every exception and its
traceback encountered by the GA during its run.
progress.log
is a file which lists which molecules make up each
generation, and their respective fitness values.
epp.csv
is a dumped pandas.DataFrame
which holds the data used
make epp.png
.
output.tgz
is a tarred and compressed copy of the output folder for
the run.
This means if you want to share you entire run output you can just
share this file. It can be turned off with
# some_input_file.png
tar_output = False
Finally, when running the GA the progress will be printed into stderr. The message should be relatively straightforward. One thing to note though is that during optimizations and fitness function calculation, any molecule that has already been optimized and had its fitness value calculated will be skipped, so that duplicate work is avoided. Briefly an example message
======================================================================
17:42:20 - INFO - stk.ga.mutation - Using random_bb.
======================================================================
show the time, the level of the message which can be, in order of priority DEBUG, INFO, WARNING, ERROR or CRITICAL, the module where the message originated and finally the message itself.
Extending stk
¶
Each module of stk
has its own guidelines for adding new functionality.
However, in almost all cases adding new features to stk
only involves
defining a simple function in the appropriate module or a method in the
appropriate class.
- Extending stk: Adding new macromolecules.
- Extending stk: Adding new topologies.
- Extending stk: Adding more functional groups.
- Extending stk: Adding optimization functions.
- Extending stk: Adding more energy functions.
- Extending stk: Adding mutation functions.
- Extending stk: Adding crossover functions.
- Extending stk: Adding fitness functions.
- Extending stk: Adding normalization functions.
- Extending stk: Adding selection functions.
- Extending stk: Adding exit functions.


|
Delicious THE BEST FOOD BLOG ON THE WEB. |
POSTED ON 15 DEC 2013 / DESSERTS
For the fig-swirl: Melt butter over medium heat in a saucepan. Add brown sugar and stir to dissolve. Halve all of the figs and toss in the sauce pan with water and lemon juice. Cook over medium heat, stirring frequently, until you have chuncky-jammy mixture. Add salt with one or two stirs, set aside and let cool completely.
Ice cream: In a small pot over medium heat, combine milk, and granulated sugar until sugar is completely dissolved and the milk is barely lukewarm. Whisk in egg yolks. Set mixture in the fridge and wait until the fig mixture is cooled.
Using an ice cream machine, pour liquids into the frozen basin and process according to the manufacturer instructions, i.e., let spin and thicken for 20 minutes before adding mascarpone, fig jam mixture, and the nuts. Continue to process for +/- 10 minutes. Pour semi-frozen mixture into pyrex dish or glass tupperware. Freeze for at least two hours before serving.


[Gecode] Problem with operator== for views, equality vs. aliasing.
Mikael 'Zayenz' Lagerkvist
d00-mla at nada.kth.se
Thu May 26 11:29:16 CEST 2005
Hi,
I recently found that there is a problem with the equality-operators
for views in Gecode. The operators are defined to handle aliasing,
that is, the operation checks for usage of the same base variable.
However, the usage is (at least in some places), based on operator==
testing semantic equality. As an example, take
Int::Rel::Le<View>::post(...) from int/rel/lq-le.icc, lines 95-103:
template <class View>
ExecStatus
Le<View>::post(Space* home, View x0, View x1) {
if (x0 != x1) {
(void) new (home) Le<View>(home,x0,x1);
return ES_OK;
}
return ES_FAILED;
}
Consider this when invoked using two scale-views representing 3*x and
5*x. Then the invocation will erroneously fail.
So, what should the equality-operator mean, and what do we call the
other operation?
Regards,
Mikael
--
Mikael 'Zayenz' Lagerkvist, http://www.imit.kth.se/~zayenz/
More information about the gecode-users
mailing list


|
|
| Resource (const char *path_) |
| |
|
virtual void * | getHandle () const |
| |
|
virtual int | getWidth () const |
| |
|
virtual int | getHeight () const |
| |
|
virtual int | getLevelCount () const |
| |
|
virtual bool | isRenderable () const |
| |
|
virtual bool | isPowerOfTwo () const |
| |
|
virtual DECLARE_RESOURCE(SpriteSheet::Resource, spritesheet) protected void | onLoaded () |
| |
|
virtual void | onDestroy () |
| |
| | ResourceAccess (const char *name_) |
| | ResourceAccess Constructor. 更多...
|
| |
| virtual | ~ResourceAccess () |
| | ResourceAccess Destructor. 更多...
|
| |
| const char * | name () |
| | Get the Name. 更多...
|
| |
|
void | addReference () |
| | Increase Reference Count of the resource by 1 This function increase reference count to the resource and keep managed by the Resource Manager.
|
| |
| void | release () |
| | Decrease Reference Count of the resource by 1 This function decrease reference count to the resource. 更多...
|
| |
| int | getRefCount () const |
| | Get the Reference Count of the resource. 更多...
|
| |
|
bool | isLoading () const |
| | Check if the Resource is Loading.
|
| |
|
bool | isReady () const |
| | Increase Reference Count of the resource by 1 This function increase reference count to the resource and keep managed by the Resource Manager.
|
| |


sCRIB
Cypress Point Drive Apt 254
Pictures
Notes
Rulers
Free Edit
Edit Note
New Note
Edit Pictures
New Picture


These are all the events you have submitted in priority order based on the current assessment of priorities.
| Name | Desciption | StartDateTime | EndDateTime | Location | Owner |
|---|---|---|---|---|---|
| {{=row.event_name}} | {{=row.description}} | {{=row.startdatetime.strftime("%d %b %Y %H:%M")}} | {{=row.enddatetime.strftime("%d %b %Y %H:%M")}} | {{=row.locationid.location_name}} | {{=row.owner.name}} |


The Events API is a read-only interface to all the event types that power the various activity streams on GitHub Enterprise.


Provides S4 classes and methods for reading and manipulating aligned DNA sequences, supporting an indel coding methods (only simple indel coding method is available in the current version), showing base substitutions and indels, calculating absolute pairwise distances between DNA sequences, and inferring haplotypes from DNA sequences or user provided absolute character difference matrix. This package also includes S4 classes and methods for estimating genealogical relationships among haplotypes using statistical parsimony.
| Version: | 1.0 |
| Depends: | R (≥ 3.1.1), methods, network |
| Suggests: | sna |
| Published: | 2015-04-26 |
| Author: | Caner Aktas |
| Maintainer: | Caner Aktas <caktas.aca at gmail.com> |
| License: | GPL-2 |
| URL: | http://cran.r-project.org, https://biolsystematics.wordpress.com/r/ |
| NeedsCompilation: | no |
| CRAN checks: | haplotypes results |
| Reference manual: | haplotypes.pdf |
| Package source: | haplotypes_1.0.tar.gz |
| Windows binaries: | r-devel: haplotypes_1.0.zip, r-release: haplotypes_1.0.zip, r-oldrel: haplotypes_1.0.zip |
| OS X binaries: | r-release: haplotypes_1.0.tgz, r-oldrel: haplotypes_1.0.tgz |
Please use the canonical form https://CRAN.R-project.org/package=haplotypes to link to this page.


Customer portal is designed for maintaining the data of all the customers carrying out business with the organization.


choco - Music Player
Music player created using JavaScript and HTML, which plays music according to your mood.
How are you doing today?
Select an Icon to customize your Music!
Prev
Pause
Next


Score Card
0
1
2
3
4
5
6
7
8
9
10
Running Score
Frame one
Frame two
Frame three
Frame four
Frame five
Frame six
Frame seven
Frame eight
Frame nine
Frame ten
Frame Score
New Game


Jude's Questioner
log out
Home
Questions
Author :
Jude
Question :
Will Jude come
4
2
Add Question
View Comments
Post Question


| MATLAB 文件帮助: cv.EMD | 查看 cv.EMD 的代码 | Index |
Computes the "minimal work" distance between two weighted point configurations
d = cv.EMD(signature1, signature2)
d = cv.EMD(signature1, signature2, 'OptionName', optionValue, ...)
[d, lowerBound, flow] = cv.EMD(...)
size1-by-(dims+1)
floating-point
matrix. Each row stores the point weight followed by the point
coordinates [w,x1,x2,...,xn]
. The matrix is allowed to have a single
column (weights only) if the user-defined Cost
matrix is used.
Weights can not be negative and must not all be zeros.size2-by-(dims+1)
of the same format as
signature1
, though the number of rows may be different. The total
weights may be different. In this case an extra "dummy" point is added
to either signature1
or signature2
.size1-by-size2
flow matrix of type single
.
flow(i,j)
is a flow from i-th point of signature1
to j-th point
of signature2
.d = |x1-x2| + |y1-y2|
d = sqrt((x1-x2)^2 + (y1-y2)^2)
d = max(|x1-x2|,|y1-y2|)
Cost
is set.size1-by-size2
cost matrix. Also, if a cost matrix
is used, output lower boundary lowerBound
cannot be calculated
because it needs a metric function. Not set by defaultLowerBound
(it means that the
signatures are far enough), the function does not calculate EMD. In
any case LowerBound
is set to the calculated distance between mass
centers on return. Thus, if you want to calculate both distance
between mass centers and EMD, LowerBound
should be set to 0.
default 0.The function computes the earth mover distance and/or a lower boundary of the distance between the two weighted point configurations. One of the applications described in [RubnerSept98], [Rubner2000] is multi-dimensional histogram comparison for image retrieval. EMD is a transportation problem that is solved using some modification of a simplex algorithm, thus the complexity is exponential in the worst case, though, on average it is much faster. In the case of a real metric the lower boundary can be calculated even faster (using linear-time algorithm) and it can be used to determine roughly whether the two signatures are far enough so that they cannot relate to the same object.
[RubnerSept98]:
Yossi Rubner, Carlo Tomasi, and Leonidas J Guibas. "The earth mover's distance as a metric for image retrieval". 1998.
[Rubner2000]:
Yossi Rubner, Carlo Tomasi, and Leonidas J Guibas. "The earth mover's distance as a metric for image retrieval". International Journal of Computer Vision, 40(2):99-121, 2000.


Eu sou um jovem programador, actualmente frequento o curso de Licenciatura em Engenharia Informatica na Faculdade de Engenharia da UEM, II-o nivel!
Actualmente faço parte do grupo de estudantes que estão a estagiar na Explicador Inc, ltda.
Tenho 19 anos, nos meus momentos livres gosto de ler, conversar, trocar experiências e aprender mais alguma coisa para aumentar o meu "pobre" conhecimento.
“Se estiverem a procura de um freelancer recomendo este miúdo, faz uns bons trabalhos.”
— Joaquim Mazanalo, PCA JMMTeam Inc.
“Recomendo, esse jovem ele é promissor!”
— Oscar Momed, Fundador CopeR Inc.
“Bom garoto esse, recomondo ja fiz optimos trabalhos com ele.”
— Domingos Vicente, Fundador CEDV Inc.
“Se estiver a procura de um freelancer, recomendo este carro amigo. Ele simplesmente e o melhor!!!.”
— Luis Macuvele, CEO Muca's project Inc.
Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.
A small river named Duden flows by their place and supplies it with the necessary regelialia. It is a paradisematic country, in which roasted parts of sentences fly into your mouth.
Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life One day however a small line of blind text by the name of Lorem Ipsum decided to leave for the far World of Grammar.
Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.
A small river named Duden flows by their place and supplies it with the necessary regelialia. It is a paradisematic country, in which roasted parts of sentences fly into your mouth.
Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life One day however a small line of blind text by the name of Lorem Ipsum decided to leave for the far World of Grammar.
Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life One day however a small line of blind text by the name of Lorem Ipsum decided to leave for the far World of Grammar.
Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life One day however a small line of blind text by the name of Lorem Ipsum decided to leave for the far World of Grammar.
Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
Universidade Eduardo MondlaneEven the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
Universidade Eduardo MondlaneEven the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
Universidade Eduardo MondlaneEven the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
Universidade Eduardo MondlaneEven the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
GithubEven the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
FacebookEven the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
TwitterEven the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
ShopifyEven the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.
Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic.


The {@link oaj.annotation.Beanp @Beanp} annotation is used to tailor how
individual bean properties are interpreted by the framework.
The {@link oaj.annotation.Beanp#name() @Beanp(name)} annotation
is used to override the name of the bean property.
| public class MyBean {
| @Beanp(name="Bar")
| public String getFoo() {...}
| }
The {@link oaj.annotation.Name @Name} annotation is a shortcut for specifying a bean property name:
| public class MyBean {
| @Name("Bar")
| public String getFoo() {...}
| }
If the {@link oaj.BeanContext.Builder#beanFieldVisibility(Visibility) beanFieldVisibility} setting on the bean context excludes this field
(e.g. the visibility is set to the default of PUBLIC but the field is PROTECTED), this annotation
can be used to force the field to be identified as a property.
| public class MyBean {
| @Beanp
| protected String getFoo() {...}
| }
The bean property named "*" is the designated "dynamic property" which allows for "extra" bean
properties not otherwise defined.
This is similar in concept to the Jackson @JsonGetterAll and @JsonSetterAll
annotations but generalized for all supported marshall languages.
The primary purpose is for backwards compatibility in parsing newer streams with addition
information into older beans.
The following shows various ways of using dynamic bean properties.
| // Option #1 - A simple public Map field.
| // The field name can be anything.
| public class BeanWithDynaField {
|
| @Beanp("*")
| public Map<String,Object> extraStuff = new LinkedHashMap<String,Object>();
| }
|
| // Option #2 - Getters and setters.
| // Method names can be anything.
| // Getter must return a Map with String keys.
| // Setter must take in two arguments, a String and Object.
| public class BeanWithDynaMethods {
|
| @Beanp("*")
| public Map<String,Object> getMyExtraStuff() {
| ...
| }
|
| @Beanp("*")
| public void setAnExtraField(String name, Object value) {
| ...
| }
| }
|
| // Option #3 - Getter only.
| // Properties will be added through the getter.
| public class BeanWithDynaGetterOnly {
|
| @Beanp("*")
| public Map<String,Object> getMyExtraStuff() {
| ...
| }
| }
Similar rules apply for value types and swaps.
The property values optionally can be any serializable type or use swaps.
| // A serializable type other than Object.
| public class BeanWithDynaFieldWithListValues {
|
| @Beanp("*")
| public Map<String,List<String>> getMyExtraStuff() {
| ...
| }
| }
|
| // A swapped value.
| public class BeanWithDynaFieldWithSwappedValues {
|
| @Beanp(name="*", swap=TemporalCalendarSwap.IsoOffsetDateTime.class)
| public Map<String,Calendar> getMyExtraStuff() {
| ...
| }
| }
Note that if you're not interested in these additional properties, you can also use the
{@link oaj.BeanContext.Builder#ignoreUnknownBeanProperties() ignoreUnknownBeanProperties} setting to ignore values
that don't fit into existing properties.
The {@link oaj.annotation.Beanp#value() @Beanp(value)} annotation
is a synonym for {@link oaj.annotation.Beanp#name() @Beanp(name)}.
Use it in cases where you're only specifying a name so that you can shorten your annotation.
The following annotations are equivalent:
| @Beanp(name="foo")
|
| @Beanp("foo")
The {@link oaj.annotation.Beanp#type() @Beanp(type)} annotation
is used to identify a specialized class type for a generalized property.
Normally the type is inferred through reflection of the field type or getter return type.
However, you'll want to specify this value if you're parsing beans where the bean property class
is an interface or abstract class to identify the bean type to instantiate.
Otherwise, you may cause an {@link java.lang.InstantiationException} when trying to set these fields.
This property must denote a concrete class with a no-arg constructor.
| public class MyBean {
|
| // Identify concrete type as a HashMap.
| @Beanp(type=HashMap.class)
| public Map p1;
| }
The {@link oaj.annotation.Beanp#params() @Beanp(params)} annotation
is for bean properties of type map or collection.
It's used to identify the class types of the contents of the bean property object when
the general parameter types are interfaces or abstract classes.
| public class MyBean {
|
| // This is a HashMap<String,Integer>.
| @Beanp(type=HashMap.class, params={String.class,Integer.class})
| public Map p1;
| }
The {@link oaj.annotation.Beanp#properties() @Beanp(properties)}
annotation is used to limit which child properties are rendered by the serializers.
It can be used on any of the following bean property types:
- Beans - Only render the specified properties of the bean.
- Maps - Only render the specified entries in the map.
- Bean/Map arrays - Same but applied to each element in the array.
- Bean/Map collections - Same but applied to each element in the collection.
| public class MyClass {
|
| // Only render 'f1' when serializing this bean property.
| @Beanp(properties={"f1"})
| public MyChildClass x1 = new MyChildClass();
| }
|
| public class MyChildClass {
| public int f1 = 1;
| public int f2 = 2;
| }
|
| // Renders "{x1:{f1:1}}"
| String json = Json.of(new MyClass());
The {@link oaj.annotation.Beanp#format() @Beanp(format)}
annotation specifies a String format for converting a bean property value to a formatted string.
| // Serialize a float as a string with 2 decimal places.
| @Beanp(format="$%.2f")
| public float price;


?Wellesley
College
Wellesley
College
Herbarium
(WELC)
Donated
to
NY
in
1988
HERBARIUM
OF
F.
W.
HUNNEWELL
PARISH
„NEW
BOTANICAi
S^ARDE**-
Garden
1tST7St
1659756
Legend -
Level of confidence that token is an accurately-transcribed word
extremely low
very low
low
undetermined
medium
high
very high


Recap
In the last post about descriptors I introduced the concept of building an observer pattern with descriptors, something Chris Beaumont almost teases with in his Python Descriptors Demystified. But, I feel he left a lot on the table with that concept.
Before delving deep into the code (and this post is going to be very code heavy), let's recap what we learned last time:
- Learned about how Python handles attribute access on objects.
- What the descriptor protocol is and how to briefly implement it
- Stored the data on the object's __dict__
- Used a metaclass to handle registering the descriptors for us.
And now for a little bit of code dump to get it active in this notebook as well as reminding us what it looks like:
class Descriptor: def __init__(self, name=None, *args, **kwargs): super().__init__(*args, **kwargs) self.name = name class checkedmeta(type): def __new__(cls, clsname, bases, methods): # Attach attribute names to the descriptors for key, value in methods.items(): if isinstance(value, Descriptor): value.name = key # really we should use super rather than type here return super().__new__(cls, clsname, bases, methods)
Callbacks
Callbacks are simply actions that run in response to something. They allow external code to react and hook into your code. This style of programming is very common, for example, in Node.js. These can be utilized in Python as well. For now, I'm going to stick with my business crucial to_lower as our callback to give an example before moving on to actually working with the observer pattern.
# pretend this lives at in a package called critical # and actually does something really useful def to_lower(value): return value.lower() def print_lower(value): print(to_lower(value)) #from critical import print_lower def my_business_logic(value, callback): remove = 'aeiou' value = ''.join([c for c in value if not c.lower() in remove]) callback(value) return value my_business_logic('Alec Reiter', callback=print_lower)
lc rtr
'lc Rtr'
Now, the callback could have done anything like updating a database, sending a tweet or simply plug it into a grander processing framework. Node.js uses callbacks for things like error handling on view functions. This is just to give an idea of what's happening in a basic sense. Your code runs and then sends a request to the callback for more action. Implementing call back descriptors is pretty easy.
class CallbackAttribute(Descriptor): def __init__(self, callback=None, *args, **kwargs): super().__init__(*args, **kwargs) self.callback = callback def __set__(self, instance, value): instance.__dict__[self.name] = value if self.callback: self.callback(instance, self.name, value) def frobed_callback(instance, name, value): print("Set {} on {!s} to {}".format(name, instance, value)) class Thing(metaclass=checkedmeta): frob = CallbackAttribute(callback=frobed_callback) def __init__(self, frob): self.frob = frob foo = Thing(frob=4)
Set frob on <__main__.Thing object at 0x7f0d2c2c6358> to 4
Of course this is an incredibly limited callback descriptor, we're limited to only one callback that's set at class definition time. But it's merely to serve as an example of what's to come.
Observers
According to wikipedia,
The Observer Pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.
And according to the Gang of Four:
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
The Gang of Four moves on to state that observers and subjects shouldn't be tightly coupled because it reduces the ability to reuse them else where. Put plainly, your subject shouldn't have hard coded logic to call to specific observers. Rather, you should be able to register instances of observers onto an object (or class) and have it call out to them programmatically.
You might run into other names such as Event Handler, PubSub/Publisher-Subscriber, or Signals. These are all variations (to my best understanding) on the pattern with minute but important differences. I won't delve into them, but the take away is that all four of these follow the same basic pattern: An object hooks callbacks which run when they're notified of something.
An easy implementation of this would look like this:
from abc import ABCMeta, abstractmethod class SubjectMixin: """Mixin that will allow an object to notify observers about changes to itself.""" def __init__(self, observers=None, *args, **kwargs): super().__init__(*args, **kwargs) self._observers = [] if observers: self._observers.extend(observers) def notify(self): for observer in self._observers: observer.update(self) def add_observer(self, observer): if observer not in self._observers: self._observers.append(observer) def remove_observer(self, observer): if observer in self._observers: self._observers.remove(observer) class ObserverMixin(metaclass=ABCMeta): """Mixin that will allow an object to observe and report on other objects.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @abstractmethod def update(self, instance): return NotImplemented
An initial attempt at this pattern will use inheritance (or interfaces if you're using something like PHP or Java where single inheritance is the only option). The pattern is simple:
- We store observers in a private (or at least as private as Python allows) list
- When we need to notify the observers, we do so explicitly by hitting all of them and their update method
Observers are free to implement update in whatever way, but they must implement it. A simple implementation might look like this.
class Person(SubjectMixin): def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.name = name class PrintLowerNoVowels(ObserverMixin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def update(self, instance): remove = 'aeiou' value = instance.name.lower() value = ''.join([c for c in value if not c in remove]) print(value) plnv = PrintLowerNoVowels() me = Person(name="Alec Reiter", observers=[plnv]) me.notify()
lc rtr
This is generally how it's implemented -- at least in most of the articles I read. It's also possible to automate the notification via property. Say, we wanted to notify the observers every time we change the name attribute on a Person instance. We could write that logic every where. Maybe apply it with a context manager or decorator. But, tying it to the object makes the most amount of sense.
class Person(SubjectMixin): def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.__name = None self.name = name @property def name(self): return self.__name @name.setter def name(self, value): if value != self.__name: self.__name = value self.notify() me = Person(name="Alec Reiter", observers=[plnv])
lc rtr
If we're concerned about automatically notifying the observers any time an attrbute is changed, we could just override __setattr__ to handle this for us. Which circumvents the needs to write properties for every attribute if this is the only action we're concerned with. It's super easy to implement as well.
class Person(SubjectMixin): def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.name = name def __setattr__(self, name, value): super().__setattr__(name, value) self.notify() me = Person(name="Alec Reiter", observers=[plnv])
lc rtr
And that's all well and good. Not to mention a good deal less complicated that what I'm about to delve into. But it's also less fun for me. I'm not going to advocate for one of these implementations over the other except to say the one I'm going to focus on will offer a much finer grain of control.
Watching specific attributes
However, if we're concerned with monitoring specific attributes for changes, descriptors are the correct way to handle this. Why bother emitting an event every time age is changed if we only care about name or email?
The first step is to identify the logic we'd end up repeating in each property and moving that into a seperate object. We'll call this new class WatchedAttribute.
class WatchedAttribute(Descriptor): def __init__(self, name=None, *args, **kwargs): super().__init__(name, *args, **kwargs) def __set__(self, instance, value): if self.name not in instance.__dict__ or value != instance.__dict__[self.name]: instance.__dict__[self.name] = value instance.notify() class Person(SubjectMixin, metaclass=checkedmeta): name = WatchedAttribute() def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.name = name me = Person(name="Alec Reiter", observers=[plnv]) me.name = "Alec Reiter"
lc rtr
Now, we can add multiple attributes that are watched without rewriting the property each time to change the variable name. If we split the name attribute into first and last names, if we add an email attribute it's easy. Just add another WatchedAttribute entry on the class level and set it in __init__.
But I feel we can improve on this pattern as well. There's two big things I'm not a fan of with this implementation:
- We manipulate the underlying dictionary to store the values.
- The Subject is responsible for notifying the Observers.
We can fix both of these things, but the first will take us down a side road.
Alternative Data Store
The first issue is trickier. We need to relate instances to values without creating a mess we'll have to clean up later, or creating a memory leak that will absolutely murder a long running process. The most effective way of handling both of these is using weak references.
References
CPython (the implementation I'm using) utilizes reference counting to determine if an object should be garbage collected. When an object's reference count drops to 0, it's space in memory can be reclaimed by Python for use else where. Sometimes we only want to hold a reference to an object but not so tightly it won't be garbage collected if we forget about it. Consider this:
print(me) registry = {"me" : me}
<__main__.Person object at 0x7f0d2c2c64e0>
Storing instances in a dictionary as keys or values (or in a list or set) as a form of caching is extremely common. But if we remove all the other instances of the object laying around...
del me
...that reference is left hanging around:
me = registry['me'] print(me)
<__main__.Person object at 0x7f0d2c2c64e0>
Before this gets too side tracked into weak references, I want to note that they're not a silver bullet and require a little more knowledge about Python to use efficienctly. You can still shoot your foot off with them. In this case, we're not using them prevent cycles but to instead maintain a cache.
Peter Parente wrote about weak references on his blog and while some of the information is out dated (the new module was deprecated in 2.6 and replaced with types), it's still relevant to understanding what weak references are. And Doug Hellman explored the weakref module in his Python Module of the Week series.
But the short of it is that an instance of WeakKeyDictionary, WeakValueDictionary or WeakSet will prevent this. Most things can be weak referenced -- the documentation goes into detail about what can be: "class instances, functions written in Python (but not in C), instance methods, sets, frozensets, some file objects, generators, type objects, sockets, arrays, deques, regular expression pattern objects, and code objects."
When you're attempting to use WeakKeyDictionary or WeakSet, the object must meet one more requirement: hashable. So objects like list or dict, even if they were implemented in Python, can't take advantage of these structures. However, outside of a few corner cases, this restraint won't affect us here.
Implementing it is incredibly easy.
from weakref import WeakKeyDictionary class WatchedAttribute(Descriptor): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.values = WeakKeyDictionary() def __get__(self, instance, cls): return self.values[instance] def __set__(self, instance, value): if instance not in self.values or value != self.values[instance]: self.values[instance] = value instance.notify() class Person(SubjectMixin): name = WatchedAttribute() def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.name = name me = Person(name="Alec Reiter", observers=[plnv])
lc rtr
You'll notice the metaclass we were using before is also gone now. That's because since we're storing the information on a cache inside the descriptor, it no longer needs to worry about what name it's being held under.
Descriptors as Subjects
The next issue was moving the publishing of events out of the main object. The main reason for this would be to notify only certain subscribers when an attribute changes but not all of them. This explores what happens when access a descriptor through the class and not an instance. Meaning answering, "What does cls (or type) do on __get__?
Accessing the Descriptor
Since descriptors are objects that just happen to follow a certain protocol that doesn't mean they can't have other methods on it. Or even follow multiple protocols. An object could be both a descriptor and an iterator for example. However, getting to these other methods can be tricky. We obviously can't do it through an instance, Python resolves that access to the __get__ method and returns a value.
This means we have to go through the class. But the way our descriptor is set up, it'll blow up when an instance isn't passed to it. We could simply return the instance of the descriptor when an instance isn't passed...would it work? Spoilers: It does. So we can fully move the registration of observers and notification out into the descriptors and our SubjectMixin can be redefined to work with our descriptor.
Actually, we end up redefining the Descriptor and WatchedAttribute classes as well. Forewarning, this is a bit of a code dump.
from weakref import WeakSet class SubjectMixin: def __init__(self, observers=None, *args, **kwargs): self._observers = WeakSet() super().__init__(*args, **kwargs) if observers: self._observers.update(observers) def notify(self, instance): for observer in self._observers: observer.update(instance) def add_observer(self, observer): self._observers.add(observer) def remove_observer(self, observer): if observer in self._observers: self._observers.remove(observer)
class CachingDescriptor(Descriptor): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._instances = WeakKeyDictionary() def __get__(self, instance, cls): if instance is None: return self return self._instances[instance] def __set__(self, instance, value): self._instances[instance] = value
class WatchedAttribute(CachingDescriptor, SubjectMixin): def __init__(self, observers=None, *args, **kwargs): super().__init__(observers=observers, *args, **kwargs) def __set__(self, instance, value): super().__set__(instance, value) self.notify(instance) class Person: name = WatchedAttribute() def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.name = name Person.name.add_observer(plnv) me = Person(name="Alec Reiter")
lc rtr
There's some subtle changes going on here that you might miss unless you explicitly diff the preceeding implementation of SubjectMixin with this one.
The observer container is changed from a list to a WeakSet. Both are iterable, which means notify doesn't change (at least due to this). WeakSet plays off both the strengths of sets (which only contain unique items) and weak references. The only thing that WeakSet won't handle is keeping the observers in any particular sort of order and dealing with unhashable types -- neither of which affect us. You'll notice that adding elements to a set is slightly different from a list, so it's not a complete drop in replacement.
I will note I went back and forth between using WeakSet and a regular set. Mostly because if we remove all other references from an observer, do we intend to still have the observer still process requests? My thoughts on the matter is no, the observer should be considered dead. In other cases, the goal could be to have "anonymous" observers -- objects that are created and immediately injected into the framework rather than assigned to a name and passed in. If this is the desire, than WeakSet wouldn't keep the object from being immediately garbage collected. I'll leave the pros and cons of both approaches as an exercise to the reader. ;)
The next subtle difference is that SubjectMixin.notify now accepts an instance explicitly. Since we've displaced this logic to the descriptor, passing self to it ends up passing the instance of the descriptor rather than an instance of the class it's attached to.
Other than that, it's just a matter of knowing how multiple inheritance works. Which is a completely separate matter best left to another time. It involves liberal use of super to say the least.
The short of it is that WatchedAttribute combines the methods and data from both Descriptor and SubjectMixin together. Meaning Descriptor can worry about being a descriptor that stores information in a weak ref dictionary. And SubjectMixin can worry about being the basis for observed subjects -- it's applicable for both descriptors and other objects. WatchedAttribute just overrides how Descriptor.__set__ operates (or rather extends it if you want to split hairs) to combine the two fully.
Going Further
We could, of course, go further to registering observers for every instance of an object with the WatchedAttribute and specific instances as well. Implementing this is a just a mite trickier, but not terribly. The first step is to imitate the behavior of collection.defaultdict in WeakKeyDictionary. Emulating defaultdict is pretty straight foward and just depends on defining __missing__, setting a hook for it in __getitem__ and providing a constructor.
The reason for building this is to utilize WeakSet as a way to hold onto observers for us that are local to a particular instance.
class WeakKeyDefaultDict(WeakKeyDictionary): def __init__(self, default_factory=None, *args, **kwargs): super().__init__(*args, **kwargs) self.default_factory = default_factory def __getitem__(self, key): try: return super().__getitem__(key) except KeyError: return self.__missing__(key) def __missing__(self, key): if not self.default_factory: raise KeyError(key) value = self.default_factory() super().__setitem__(key, value) return value
With that built, we can reconstruct WatchedAttribute to hold both "global" and "local" observers.
class WatchedAttribute(CachingDescriptor, SubjectMixin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._local_observers = WeakKeyDefaultDict(WeakSet) def __set__(self, instance, value): super().__set__(instance, value) self.notify(instance) def add_observer(self, observer, instance=None): if instance is None: super().add_observer(observer) else: self._local_observers[instance].add(observer) def remove_observer(self, observer, instance=None): if instance is None: super().remove_observer(observer) else: if observer in self._local_observers[instance]: self._local_observers[instance].remove(observer) def notify(self, instance): observers = self._observers | self._local_observers[instance] for observer in observers: observer.update(instance)
The real question, now, is how does it handle? It should handle the same as previous iterations on WatchedAttribute except for the specific behavior we've overriden here. I'm also going to add some convience methods to the Person class to make it slightly easier to interact with the observers.
class Person: name = WatchedAttribute() def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.name = name def access_watched(self, attr): return getattr(self.__class__, attr) def attach(self, attr, observer, global_=False): watched = self.access_watched(attr) inst = None if global_ else self watched.add_observer(observer, inst) def detach(self, attr, observer, global_=False): watched = self.access_watched(attr) inst = None if global_ else self watched.remove_observer(observer, inst) class PrintUpper(ObserverMixin): def update(self, instance): print(instance.name.upper()) pu = PrintUpper() me = Person(name=None) me.attach('name', plnv, global_=True) me.attach('name', pu) me.name = "Alec Reiter"
lc rtr ALEC REITER
other = Person(name="Ol' Long Johnson")
l' lng jhnsn
As we can see, the observer that prints the value of Person.name in upper case is bound only to the first instance of Person, where as the one that strips out the vowels and prints that result is bound to all of instances. It's also possible to create an ignore method that would allow specific instances to ignore certain observers as well. Or even better, create a set of rules that can be followed: "Only invoke this observer if the value doesn't change."
Something I've curiously ignored is pre-subscribing observers. That is to say, when we create the class we attach a predetermined list of observers to the attribute. This is a feature of the original SubjectMixin class and is inherited to WatchedAttribute (or as Raymond Hettinger would put it: WatchedAttribute delegates the work to SubjectMixin).
class Person: name = WatchedAttribute(observers=[plnv]) def __init__(self, name, *args, **kwargs): super().__init__(*args, **kwargs) self.name = name def access_watched(self, attr): return getattr(self.__class__, attr) def attach(self, attr, observer, global_=False): watched = self.access_watched(attr) inst = None if global_ else self watched.add_observer(observer, inst) me = Person(name="Alec Reiter")
lc rtr
Fin
This method of implementing the observer pattern allows a lot of very fine grained control. I'm not advocating it as a good solution -- or even a workable solution on its own. There's plenty that's left on the table as far as details and issues go. For example, how would this expand to using a messaging queue (ZeroMQ or Redis) to publish events to? Or how does it interact with asyncio or twisted? Integrating this pattern with an existing framework (blinker for example) would probably be the best solution
Rather, it's meant as an introduction to the true power of what you can do with descriptors beyond just making sure a string is all lower case or normalizing floating point numbers to decimal.Decimal instances. Which are valid uses of descriptors, don't take that the wrong way.
Some of the concepts introduced here -- manipulating descriptors on both the instance and class levels -- are used to build tremendously flexible systems. Ever wonder how SQLAlchemy seems to magically treat class attributes as parameters in search queries but then magically they're filled with data on the instance level? Descriptors and that if instance is None check.
I spilled my brains, spill some of yours.


--- layout: page title: Glossary ---
Information management and metadata management practitioners throw around a lot of technical terms. Let us guide you through some of the key concepts to understand.


--- layout: newsstory title: IT WAS THE WORST match: FAC2Q - Oadby 2 Yeltz 1 ---
I usually try and make an effort to put a positive slant on things, as there's enough people around who'll moan if they get half a chance. However this time I'm really struggling.
They were rubbish. They're a West. Mids. League standard team if you can remember back to those days, and in the first half we outclassed them, leading 1-0 at the break with a nice goal from Lyndon Rowlands .
However, only one team seemed to remember it was the FA Cup in the second half. They battled and scrapped for everything and once they'd snuck an equaliser , we went completely to pieces.
Whether it was because Birchy had got injured, but no-one (on our side) seemed to have any idea about what to do, and it wasn't a great surprise when they scored the winner . It was a sort of breakaway goal, but describing it like that gives the impression that we were mounting some kind of pressure at the other end.
We were desperate for a decent cup run to spark the season into life, and now we're left feeling worse than ever. Very poor .
If you've got anything to say about all of this, I'm sure there will be much discussion this week on the Yeltz mailing list .


This tool aim to humbly participate in stopping the race for ever more
quality and bandwidth (8K resolution, 5G network, etc.) by offering a
simple way to radically reduce the size of a video.
The digital world’s contribution to the footprint of humanity is
currently around 4% (see
this report from GreenIT.fr
and
this another report from The Shift Project). This is more than
the aviation, and it is predicted to grow in the future.
Online video does NOT represent the main impact of the digital
world, manufacturing is a much bigger deal. But reducing the
size of a video can help keeping our old devices that have
limited bandwidth and limited computing power, instead of buying new
ones.
Apply settings from The Shift Project (720p, CRF 28, 160 kbits/s)
The Shift Project has published a guide for reducing the size of a
video while maintaining a good quality
You can download it
here.
Basically, it reduces the video resolution to 720p and the audio
bitrate to 160 kbits/s. The Constant Rate Factor (CRF) is set to 22.
Lower video resolution (480p)
It reduces the video resolution to 480p. Don't watch it on your 4K TV,
otherwise it is OK.
Lower video quality (CRF 28)
It reduces the Constant Rate Factor (CRF) to 28. You won't see tiny
details but the essential is there.
Lower audio bitrate (56 kbits/s)
It reduces the audio bitrate to 160 kbits/s. If the audio is mainly
speeches, it should remain audible.
One image every 5 seconds (!)
For some videos, like conferences, there is not much action and you
can easily understand what happens even with one image every 5 seconds
Black and white
Aesthetic and lightweight
This tool uses
FFMPEG.WASM
to edit the video directly in the browser!
You can dowload
FFMPEG
to try these settings directly on your computer
Apply settings from The Shift Project (720p, CRF 28, 160
kbits/s)
ffmpeg -i input.mp4 -s hd720 -c:v libx264 -crf 22 -vf "scale=iw*sar:ih,setsar=1" -c:a aac -b:a 160k output.mp4
Lower video resolution (480p)
ffmpeg -i input.mp4 -s hd480 -c:v libx264 -crf 22 -vf "scale=iw*sar:ih,setsar=1" output.mp4
Lower video quality (CRF 28)
ffmpeg -i input.mp4 -c:v libx264 -crf 28 -vf "scale=iw*sar:ih,setsar=1" output.mp4
Lower audio bitrate (56 kbits/s)
ffmpeg -i input.mp4 -c:a aac -b:a 56k output.mp4
One image every 5 seconds
ffmpeg -i input.mp4 -vf "fps=fps=1/5" output.mp4
Black and white
ffmpeg -i input.mp4 -vf "hue=s=0" output.mp4
This whole approach is inspired by image dithering (see
here for an
example), which removes a lot of data in the image while preserving
its essential meaning


Preparation time
less than 30 mins
Cooking time
30 mins to 1 hour
Serves
Makes 9 brownies
Dietary
These chocolate brownies are have fewer calories than a typical brownie, but they're just as delicious and easy to make.
Each brownie provides 222 kcal, 3.7g protein, 23.5g carbohydrate (of which 17g sugars), 13g fat (of which 3.6g saturates), 1.4g fibre and 0.6g salt.
Preheat the oven to 190C/170C Fan/Gas 5. Grease and line an 18cm/7in square deep cake tin.
Beat together the sunflower spread, eggs and sugar. Stir in the flour and cocoa powder, then add the chocolate and chocolate extract. Stir in 1 teaspoon of boiling water and a pinch of salt.
Transfer the mixture to the prepared tin and bake for 30 minutes, or until a skewer comes out clean when inserted in the centre.
Leave to cool in the tin then cut into 9 squares. Dust with a little cocoa powder and serve.


Uzhgorod stabbing: One serviceman injured
The conflict sparked between the military at a local army base.
Police Department in Ukraine's Zakarpattia region reported that a conflict had arisen between military servicemen at an army base in the city of Uzhgorod on December 8.
An altercation grew into a fight, where one of the military was stabbed.
A 52-year-old military was hospitalized on Sunday evening, the police press service said on December 9.
It turned out that a 31-year-old contract soldier stabbed the military at the military base premises.
The police have opened criminal proceedings into attempted murder. The attacker was detained.
Law enforcers are establishing the circumstances of the incident.
As UNIAN reported earlier, two people died as a result of a conflict between foreigners and local residents in the center of Odesa.


Click here to register for our spring 2019 food swap
Bring your homemade or homegrown items for a barter style swap! Meet fellow foodies, bakers, gardeners, farmers and local like-minded people. Bring an old friend or come and make new friends. Serving the Wilmington, Delaware area.
Click here to register for our spring 2019 food swap
Wilmington Food Swap is a community of local foodies who share a passion for homemade, homegrown, or foraged foods.
Starting Spring 2019, we will meet quarterly to swap and sample each others kitchen creations. While this event is open to anyone, registration in advance is required to attend.
For information about how you can help, see our Support Us page.
A food swap is a quarterly event where you and fellow foodies meet to exchange and share their homemade, homegrown, or foraged foods with each other. Food swaps are a great way to change up the homemade and homegrown foods in your pantry, while getting to meet local foodies like yourself in the process.
Take a minute and review our Tips For Successful Swapping
In truth, the sky is the limit. A loaf of bread, eggs if you raise chickens or vegetables from your garden. Jams, jellies and marmalade are frequently swapped at these events. Get creative with pasta, granola, kombucha, or condiments. Candies and cookies are great as well, but be mindful of portion size. Someone who made a pint of jam probably would not want to make a swap for just one or two cookies. Whatever you decide to bring, make sure that it’s packaged in bags or jars and properly labeled.
It's recommended you bring five to ten items you wish to swap, as well as samples or a potluck dish to share with the group.
Hi there! You can use this contact form to reach out with any questions you may have about who we are, what a food swap is, ideas of what to bring to swap, or anything else.
Additionally, if you have a venue you’d be willing to let us have a meet at, or want to know if we need any help with supplies, feel free to reach out also.
You can also use our email address below if you prefer.
We look forward to hearing from you!


Next.js supports IE11 and all modern browsers (Edge, Firefox, Chrome, Safari, Opera, et al) with no required configuration.
We transparently inject polyfills required for IE11 compatibility. In addition, we also inject widely used polyfills, including:
whatwg-fetch
and unfetch
.
url
package (Node.js API).
object-assign
, object.assign
, and
core-js/object/assign
.
If any of your dependencies includes these polyfills, they’ll be eliminated automatically from the production build to avoid duplication.
In addition, to reduce bundle size, Next.js will only load these polyfills for browsers that require them. The majority of the web traffic globally will not download these polyfills.
In addition to fetch()
on the client side, Next.js polyfills
fetch()
in the Node.js environment. You can use
fetch()
on your server code (such as
getStaticProps
) without using polyfills such as
isomorphic-unfetch
or node-fetch
.
If your own code or any external npm dependencies require features not supported by your target browsers, you need to add polyfills yourself.
In this case, you should add a top-level import for the
specific polyfill you need in your
Custom <App>
or the individual component.
Next.js allows you to use the latest JavaScript features out of the box. In addition to ES6 features, Next.js also supports:
import()
(ES2020)
Next.js has built-in TypeScript support. Learn more here.
You can customize babel configuration. Learn more here.