User Persona: Chris Smith
Persona
- Name: Chris Smith
- Age: 33
- Ethnicity:Caucasian
- Location: Albuquerque, NM
- Job:Tech Recruiter
- Technology:
- Phone: Samsung S9 Midnight Black 64 gb
- Laptop: Dell - Inspiron 17.3" Laptop - Intel Core i7 - 8GB Memory - 2TB Hard Drive - Silver, Windows 10 OS.
- Hobbies: plays basketball with friends, hiking, keeping up to date on tech news, tries new microbreweries
- Favorite Websites: github.com, linkedin.com, stackoverflow.com
- Behaviors:Loves his job but is a bit of a workaholic, wants to find someone to share his life with and start a family.
- Attitudes: Wants to settle down and start a family and is open to online dating sites he hadn't considered before.
- Frustrations:Doesn't want to use the hook-up apps because he is looking for a serious relationship and doesn't want to waste time with flings.
- Goals: Find a wife.
User Story
As a user, I am desperate to meet the perfect woman, get married and start a family, at any cost.
Use Case
Title: Receives an email notification
Description: Chris receives an email notification from dating site URL, logs into site to check status updates
Name of the User and Their Role:Chris Smith--potential love match
Usage Preconditions: Must have internet capable device, must be logged in
Usage Post-conditions: Server sends a message to Chris' most recent match and saves his most recent Personality updates
Interaction Flow:
- Chris receives an email notification from blamedandatedan.online, his new favorite dating website.
- After work, at home, Chris opens his email account in Chrome to look at email and sees that it is a message from a new match!
- After Chris reads the email he decides to respond so he enters blamedandatedan.online in Chrome.
- Server receives the request and, since Chris is still logged in, returns Chris' profile page.
- Chris looks to the menu on the left side of the page and finds the link for his Match List and clicks it.
- Server receives the request and returns the page containing an array of the profiles Chris has liked.
- Chris looks for the woman who just messaged him and notices that the heart next to her name is now illuminated; he clicks the link to her profile.
- Server receives request and returns the page for Chris' match.
- Chris looks through her page noticing that there is now new content to view including a message box. Chris enters a message and his information into the form and clicks submit.
- Server receives request and sends an email notification to his match's email account.
- Chris now decides to update his Personality section, so he looks to the menu again and clicks the link to his Personality editor page.
- Server receives the request and returns the editor page.
- Chris updates his Personality section with his likes and dislikes and clicks finish.
- Server receives request and and saves the new information.
- Chris uses the profile link in the menu to return to his page
- Server receives request and returns Chris' profile page.
- Chris can now see that his information has updated. He is happy with this so he closes the window but doesn't log out.
Frequency of Use: Daily


Privacy Policy
Your privacy is important to us and GTmetrix ("we", "us", "our") is committed to keeping your information secure. This Privacy Policy is provided to help you better understand how we collect and use your information.
This policy is effective as of May 25th, 2018.
What information do we collect?
We collect information about you when you provide it to us and when you use GTmetrix, as described below.
Information you provide to us
We collect information about you that you provide to us:
- Basic Account information: If you register for a GTmetrix account, we collect your name (optional) and e-mail address.
- Payment information: If you sign up for a GTmetrix PRO account, we collect your payment information.
- Test details: If you use the test options (e.g. Cookies, HTTP authentication) when performing a GTmetrix test, those settings are saved for future tests.
- Communications with us: If you contact us via the Contact form, e-mail or social media, this information is collected.
Information we collect automatically
We also collect some information automatically:
- Logs: Like most services, we log access to our services in log files. This data includes date and time of access, IP address, browser user agent and the page visited.
- Usage information: We collect information on how you are using GTmetrix.
- Cookies / Web storage: We use cookies and web storage (i.e. localStorage/sessionStorage) for the sole purpose of preserving state. For example, to remember who you are logged in as, or to remember where you are in performing a task.
Information we receive from other sources
The only third party source we collect information from is Google Analytics; a web analytics service provided by Google Inc. Google Analytics uses cookies to enable analysis of your use of the website.
In using Google Analytics, GTmetrix employs the "anonymizeIp" feature which masks part of your IP address before storing or processing it.
Our Google Analytics is configured to disable all data sharing options (i.e. our Google Analytics data is not shared with other Google products and services). Google Analytics' advertising features are also disabled (i.e. Remarketing and Advertising Reporting features).
You can disable Google Analytics tracking completely by using the Google Analytics Opt-out browser add-on.
How do we use this information?
We use the information mentioned above:
- To provide and personalize GTmetrix: We use your information to provide services to you (e.g. monitoring alerts) and to personalize your GTmetrix experience.
- To communicate with you about GTmetrix: We use your contact information to send you e-mail directly relating to GTmetrix (e.g. account validation, onboarding, PRO subscription, monitored page alerts). If you have opted-in, we also send you other non-essential GTmetrix e-mail (e.g. Newsletter, Tips and Insights, Promotions). You can change your communications settings from the User Settings page.
- To resolve customer support issues: When you contact us for support, we may use your information to help resolve your problem.
- To improve GTmetrix: We use usage information and customer feedback to identify issues with GTmetrix and make improvements to the service.
- To monitor and prevent security issues with GTmetrix: We use logs and usage information to monitor for suspicious or fraudulent activity.
Do we share this information?
We do not share, sell, rent or trade your private personal information with third parties without your consent, except in the following circumstances:
-
Service Providers working on our behalf (Sub-processors): We use third-party Service Providers to provide specific services for GTmetrix. The following third-parties have limited access to your information:
- Recurly, Inc (United States): Billing and subscriptions.
- Bambora, Inc (Canada): Payment processing.
- Stripe, Inc (United States): Payment processing.
- Zendesk, Inc (United States): Customer support.
- To comply with Laws: If we receive a request for information, we may disclose information if we reasonably believe disclosure is in accordance with or required by any applicable law, regulation or legal process.
How do we store and secure this information?
Information storage and security
No service is 100% secure, but we work hard to ensure that we use best security practices when processing your information. Your information is stored as long as necessary at the following locations:
- General account and report information: GT.net (Canada)
- Payment information: Recurly (United States)
- Customer support communications: Zendesk (United States)
We do not store credit card information or any other sensitive information on our own servers.
Update and deletion of information
The following data can be accessed and updated:
- General account information: Your Name, E-mail and communication preferences can be accessed and updated from the User Settings page.
- Payment information: Your credit card details can be updated from the Payment Update page.
- Test details: Test options (e.g. Cookies, HTTP authentication) can be accessed and updated from the report's Page Settings menu.
If you would like to update/delete specific data or completely delete your account, please contact us. Note that we may need to retain certain information for record keeping purposes.
Changes to this Privacy Policy
We may make minor changes to our Privacy Policy from time to time without notice. We will post details of the changes in the Change log section below and we encourage our users to review these changes to stay informed. If you disagree with the changes to this Privacy Policy, you will need to stop using GTmetrix and request an account deletion.
How to contact us
If you have any questions or comments regarding this Privacy Policy, please contact us via our Contact form or by mail:
GTmetrix
500 - 455 Granville St
Vancouver, BC V6C 1T1
Canada
Change log
- May 25th, 2018: First revision


Created by Marco Conti<EMAIL_ADDRESS>Project page (forum, bugs, requests): https://sourceforge.net/projects/inkscapemap/
Copyright Marco Conti, 2014


“The innovative and flexible model allows us to create a training program that gives our employees the freedom to drive their own development.”
- Jack Donaghy
Product Manager, Virtual Instruments
Read all TestimonialsMore flexible training solutions for a global workforce.
Learn MoreEasily train your employees online.
Learn MoreStay competitive with on-demand training.
Learn MoreLearn how it works. Simple and easy.
“The innovative and flexible model allows us to create a training program that gives our employees the freedom to drive their own development.”
- Jack Donaghy
Product Manager, Virtual Instruments
Read all TestimonialsThe ability to effectively and efficiently use time is essential skill for every manager and team leader.
This training course on forklift safety outlines the dos and don't of forklift operation.
Accidents in long-term care facilities carry a high price. Focusing on preventing accidents before they oc...
Through this course user will get an understanding of mine ventilation systems, user will be able to design...
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore.
"Startups like OpenSesame are providing corporate "bookshelves" of these courses, making them easy for business managers to find."
Want to squeeze in some learning for your team before the end of the year, but worried you’re out of time? Have no fear! OpenSesame has you covered.
Seller DetailsTimely Intervention is based in Berkshire, England and has over 15 years’ experience delivering, designing, and deploying awarding wining learning solutions.
Seller Details


This websites makes those formated data into a way which you can visulalize!
EONET
EONET means The Earth Observatory Natural Event Tracker.Users can browse the entire globe daily and look for natural events as they occur. Storms are regularly spotted in the tropics, dust storms over deserts, forest fires in the summers.
Visit SiteMars Rover Images
Photos are organized by the sol (Martian rotation or day) on which they were taken, counting up from the rover's landing date. A photo taken on Curiosity's 1000th Martian sol exploring Mars, for example, will have a sol attribute of 1000.
Visit SiteAPOD
Each day a different image or photograph of our fascinating universe is featured, along with a brief explanation written by a professional astronomer.This website gets you the images based on the date which you enter.
Visit SiteLive ISS Position
This gets the actual position of ISS(International Space Station) and is plotted in the map.The map refreshes itself in 5s.
Visit SiteMade with by Fredy Somy


HEAD TRIP
THE CELL
Directed by Tarsem Singh
Screenplay by Mark Protosevich
With Jennifer Lopez, Vince Vaughn
UA South R 110 min
Tarsem is a successful director of music videos who has added the gravitas of a last name, Singh, for his first foray into feature films. You'd think "Singh" would work for the musical stuff, and could be dropped when he went tuneless (unless you count Howard Shore's cacophonous score.) But I digress...
His attitude toward movies seems to be that it doesn't matter what you say or do as long as it looks good. And at times it looks very good. The opening, with Jennifer Lopez swathed in brilliant white pacing the knife-edged tops of dramatically shadowed desert dunes, is the pure distilled essence of an expensive commercial. She is at the time prowling the subconscious of a small boy (more on this later), and we can only assume that this is a small boy who will grow up to be a fashion photographer - these are not images that dominate the subconscious of your typical prepubescent male.
All right, here's the deal - she's a psychologist working in an experimental scientific program that allows her, suspended in midair in a form-fitting corrugated body suit alongside her patient, to enter the kid's subconscious and find out what's gone wrong in there. The science is reminiscent of '50s sci-fi potboilers. Things aren't so bad in the little boy's brain, but they take a turn for the worse when FBI agent Novak (Vince Vaughn) finds out about this program and recruits her to take a side trip into the brain of a comatose serial killer (Vincent D'Onofrio), who has a victim stashed somewhere and there's no time to lose!
Singh cares little enough about dialogue that he allows screenwriter Mark Protosevich lines like "If we can't stop him, he ain't gonna stop himself," and to be on the safe side he imports plot and style elements from movies as diverse as "Silence of the Lambs", "Altered States", and the animated "Fantastic Planet". He has stocked his cast with middle-echelon stars, and seems not to have wasted much time directing them, with the result that Lopez spends most of her time trying to look sympathetic and concerned, Vaughn looks worried and a little lost, and D'Onofrio just looks crazy. Ultimately, Singh is banking everything on his slick visuals, and while sometimes he nails it, as often as not it gets away from him. A recurring image of Jennifer Lopez as the Virgin Mary is one that could be charitably forgotten.
If you like shots of kidnapped young women being systematically drowned in a plexiglass cell, screaming "Daddy! Mommy! Help!" as the water level rises, you'll be treated to them randomly throughout the movie. If you're fond of disemboweling and vivisection, look no further. If you're a fan of crisp story, character, and credibility, hang in there. Something's bound to turn up soon.
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


4) Data types in python¶
Related text:
- https://jakevdp.github.io/WhirlwindTourOfPython/index.html
- https://jakevdp.github.io/PythonDataScienceHandbook/
We will run some python today using variables and libraries.
Comments, Integers and floats¶
As you saw last time, basic math can be performed without importing any libraries, and python will decide if you have a integer or a float.
As engineers know, tracking units are of utmost importance. Comments can be a great way to both explain your code and track units.
In [1]:
"""
Blocks of comments can be placed between lines containing three
double-quotes, like this.
They often appear at the beginning of a function, explaining what the
function does and noting the expected input and output.
We'll come back to this later.
This is an example of commenting and using variables in a formula.
We'll use more advance math (exponents, etc.) so we'll import numpy,
an excellent math library.
"""
import numpy as np #it is very common to import numpy as the shorthand alias, 'np'
from scipy import special # we can also import just part of a library; this is needed to get erfc
# One of the most important syntax characters to know: '#' is the comment character
# They can start a line of comments only, or comments can follow code, as shown above and below.
# I'm old-school in certain ways; I explicity make values floats that
# I want treated as such, even if python will treat an integer
# variable as a float when doing the math
gas_constant = 0.00198588 # the ideal gas constant in units of kcal / (g-mol K)
temp = 300. # temp in K
energy = 5. # kcal/mol
# Save a little computation by creating a term that is repeatedly needed
ea_over_rt = energy / (gas_constant * temp)
# The (integrated form of the) Maxwell-Boltzmann distribution for the
# fraction of molecules with energy of at least E
# If consistent units were used, they should cancel out in each term
# (fractions are unitless!)
frac_mol = np.sqrt(4. / np.pi * ea_over_rt) * np.exp(-ea_over_rt) + special.erfc(np.sqrt(ea_over_rt))
print("At {} K, {}% of molecules have energy >= {} kcal/mol.".format(temp, round(frac_mol*100.,2), energy))
At 300.0 K, 0.08% of molecules have energy >= 5.0 kcal/mol.
Identifying and changing types¶
As has already appeared in ipynb’s for this course, we can find out the
type of any variable by using the built-in global function type()
.
In [2]:
print(type(temp), type(ea_over_rt))
<class 'float'> <class 'float'>
We can also change the variable type with functions such as:
In [3]:
temp = int(temp)
print(temp, type(temp))
temp = str(temp)
print(temp, type(temp))
temp = float(temp)
print(temp, type(temp))
temp = str(temp)
print(temp, type(temp))
300 <class 'int'>
300 <class 'str'>
300.0 <class 'float'>
300.0 <class 'str'>
The ability to change numbers to strings and strings to numbers can be useful when reading and writing variables.
A few more syntax tips¶
As with many other languages, there are shortcut ways of performing simple math on a variable:
In [4]:
x = 4
print("x =", x, type(x))
x += 3 # same as x = x + 3.
print("x =", x, type(x))
x -= 1 # same as x = x - 1.
print("x =", x, type(x))
x *= 3 # same as x = x * 3.
print("x =", x, type(x))
x /= 3 # same as x = x * 3.
print("x =", x, type(x))
x != 3 # same as x = x * 3.
print("x =", x, type(x))
x = 4 <class 'int'>
x = 7 <class 'int'>
x = 6 <class 'int'>
x = 18 <class 'int'>
x = 6.0 <class 'float'>
x = 6.0 <class 'float'>
The combinations of operators and the equals sign changes the pointers. What do you expect the following output to be?
In [5]:
my_favorite_number = 8
x = my_favorite_number
y = x
x *= 2
print("x =", x, "and y =", y)
x = 16 and y = 8
Note that the end of all statements is the end of the line, unlike C or
C++ which ends statements with ;
. You can force a line to wrap by
using the \
key. Even more convenient: enclose the expression in
parenthesis.
In [6]:
y = 1 + 2 + 3 + 4 + 5 + 6.
print("y = ", y, type(y))
y = 1 + 2 + 3 +\
4 + 5 + 6
print("y = ", y, type(y))
y = (1 + 2 + 3 +
4 + 5 + 6)
print("y = ", y, type(y))
y = 21.0 <class 'float'>
y = 21 <class 'int'>
y = 21 <class 'int'>
In the code above, note the indentation. As you will see even more in the future, white space is meaningful in python.
The convention is to use four spaces for indentation (and yes, there can be blocks inside blocks; the meaningful indentation can make it much easier to read!). Note that many programs automatically convert a tab to four spaces. Check whether that is happening when you tab in your notebook!
In [7]:
total = 0
for i in range(10):
# indentation indicates code block, and the first line of the block ends with ':'
print("i =", i)
total += i
print("total =", total)
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
total = 45
In [8]:
# Note the difference between this and the above code block.
total = 0
for i in range(10):
# indentation indicates code block, and the first line of the block ends with ':'
print("i =", i)
total += i
print("total =", total)
i = 0
total = 0
i = 1
total = 1
i = 2
total = 3
i = 3
total = 6
i = 4
total = 10
i = 5
total = 15
i = 6
total = 21
i = 7
total = 28
i = 8
total = 36
i = 9
total = 45
White space within lines will not affect the output. However, best practice is to put one space between each term and each operator.
Best practices in the python community are codified in the PEP 8 style guide for python code.
In [9]:
y=1+2+3+4+5+6 # saves space but is non-standard
print("y = ", y, type(y))
y = 1 +2 + 3 + 4 + 5 + 6 # this does not help readability
print("y = ", y, type(y))
y = 1 + 2 + 3 + 4 + 5 + 6 # Much better readability. Follow this lead!
print("y = ", y, type(y))
y = 21 <class 'int'>
y = 21 <class 'int'>
y = 21 <class 'int'>
Other built-in operators¶
Given the amount of material to cover in this class, we can’t spend time going over all of the built-in operators. Note that I am skipping built-in math operators including modulo, floor division, or bitwise operations. If you want to learn about them, you can start with this tutorial or always just ask the internet.
Comparison operators (== for equal to, >, <, !=, >=, and <=) will come up when we get to more into writing our own functions
Boolean operators are very readable in python. The options are True
and False
(not the capitalization), and the standard operations are
simply and
, or
, and not
. For example:
In [10]:
x = 4
(x < 6) and (x >= 2)
Out[10]:
True
Parentheses Are for Grouping or Calling (or tuples! covered below)¶
You’ve seen two ways of using parenthesis above: grouping statements or calling functions.
The terms inside the parenthesis used to call a function (like the
print
function below) are called arguments. The number of
arguments that the function takes depends on the function. In the case
of the print
function, it will print as many arguments as you give
it. However, the function type
only takes certain arguments (here,
we just give it one argument; it is possible to give it 2 specific
additional
arguments but
that is unusual and out of scope for this course).
In [11]:
y = (2 + 1 + 3)
print("y = ", y, type(y))
y = 2 * (1 + 3)
print("y = ", y, type(y))
y = (2 * 1) + 3
print("y = ", y, type(y))
y = 6 <class 'int'>
y = 8 <class 'int'>
y = 5 <class 'int'>
Other collections in python: lists, tuples, and dicts¶
A collection of values (strings, ints, floats, …) can be stored as types of collections.
The main kinds are tuples, lists, and dicts. You’ve already seen lists, remember?
In [12]:
print(type(In))
<class 'list'>
New lists can be defined without any items in them yet (an empty list) or with items. They do not have to be of the same type. Python makes a list when it sees square brackets. Items in a list do not have to be of the same type.
The built-in len()
function will return the length of the function.
In [13]:
list_1 = []
print(list_1, type(list_1), len(list_1))
list_2 = [4, 5.2, 8, 'ten', list_1]
print("list_2 = {}, has type {}, and length {}".format(list_2, type(list_2), len(list_2)))
[] <class 'list'> 0
list_2 = [4, 5.2, 8, 'ten', []], has type <class 'list'>, and length 5
As we also previously saw, we can access entries in a list. Remember that counting starts with zero. Negative numbers access items from the end of the list.
Items in a list can be changed.
In [14]:
print("At the moment, the full list_2 = ", list_2)
print(list_2[0], type(list_2[0]))
print(list_2[1], type(list_2[1]))
print(list_2[-1], type(list_2[-1]))
print(list_2[-2], type(list_2[-2]))
list_2[-2] = 10
print(list_2[-2], type(list_2[-2]))
list_2[-1] = 2
print(list_2[-1], type(list_2[-1]))
print("Now, the full list_2 = ", list_2)
print(list_2[:2])
print(list_2[1:3])
print(list_2[2:])
At the moment, the full list_2 = [4, 5.2, 8, 'ten', []]
4 <class 'int'>
5.2 <class 'float'>
[] <class 'list'>
ten <class 'str'>
10 <class 'int'>
2 <class 'int'>
Now, the full list_2 = [4, 5.2, 8, 10, 2]
[4, 5.2]
[5.2, 8]
[8, 10, 2]
Built-in methods¶
In addition to be able to use functions like print
and type
on
lists, list have built-in methods. These are particular actions that
python will know how to perform on any list. Here are a few examples;
more can be found many places, including
here.
These methods are followed by parenthesis (has parenthesis like a function) and may or may not need arguments.
In [15]:
print("list_2 = ", list_2)
list_2.sort()
print("list_2 = ", list_2)
list_2.append(7.1)
print("list_2 = ", list_2)
list_2.extend([5.3, 9.2, 4.8])
print("list_2 = ", list_2)
list_2 = [4, 5.2, 8, 10, 2]
list_2 = [2, 4, 5.2, 8, 10]
list_2 = [2, 4, 5.2, 8, 10, 7.1]
list_2 = [2, 4, 5.2, 8, 10, 7.1, 5.3, 9.2, 4.8]
If you accidentally try to make a list by using parenthesis, you’ll get a tuple instead!
In [16]:
not_a_list = ([4.3, 5.2, 8,
2, 10], [3])
print(type(not_a_list))
<class 'tuple'>
Some things are the same about tuples and lists, like how to print parts of them:
In [17]:
print(not_a_list[0], type(not_a_list[0]))
print(not_a_list[-1], type(not_a_list[-1]))
print(not_a_list[:2])
print(not_a_list[1:3])
print(not_a_list[2:])
[4.3, 5.2, 8, 2, 10] <class 'list'>
[3] <class 'list'>
([4.3, 5.2, 8, 2, 10], [3])
([3],)
()
The big difference is that tuples cannot be changed (they are immutable); you cannot change the value of an existing item or add new items.
In [18]:
not_a_list[0] = 11.11
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-18-d1adc261984b> in <module>()
----> 1 not_a_list[0] = 11.11
TypeError: 'tuple' object does not support item assignment
In [19]:
not_a_list.append(5.5)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-19-1038aa509a89> in <module>()
----> 1 not_a_list.append(5.5)
AttributeError: 'tuple' object has no attribute 'append'
However, a tuple can contain mutable items.
In [20]:
tuple_2 = ([], [1, 2, 3])
print(tuple_2)
tuple_2[0].append(5)
print(tuple_2)
tuple_2[-1][1] = 4
print(tuple_2)
([], [1, 2, 3])
([5], [1, 2, 3])
([5], [1, 4, 3])
Combinations of collections (lists of lists, tuples of lists, etc.) took my a while to wrap my head around. We’ll have more practice in the future. Also, once we get past some of these basics, we’ll get to even more fun material.
Next up: more on variables and collections


Please enter a valid contact name.
Please enter a valid contact relationship to student.
Please enter a valid contact phone number.


Websocket client
connection
Username
Join/Leave room
Join
Leave
Create/Delete room
Create
Delete
Room
Message
send
Clear text


GROFF_MOM
Section: Environments, Tables, and Troff Macros (7)Updated: 04 September 2002
Index Return to Main Contents
NAME
groff_mom - groff `mom' macrosSYNOPSIS
groff -mom [ files... ]groff -m mom [ files... ]
DESCRIPTION
mom ([lq]my own macros[rq], [lq]my other macros[rq], [lq]maximum overdrive macros[rq], ...) is a macro set for groff, designed primarily to format documents for PostScript output.mom provides two categories of macros: macros for typesetting and macros for document processing. The typesetting macros provide access to groff's typesetting power in ways that are simpler to master and to use than groff's primitives. The document processing macros provide customizable markup [lq]tags[rq] that allow the user to design and output professional-looking documents with a minimum of typesetting intervention.
mom comes with her own (very) complete documentation in HTML format.
FILES
- om.tmac
-
[en] the main macro file
-
mom.tmac
[en] a wrapper file that calls om.tmac directly.
- [en] entry point to the HTML documentation
- /usr/share/doc/groff/<IP_ADDRESS>/examples/*.mom
- [en] example files using mom
AUTHOR
mom
Index
This document was created by man2html, using the manual pages.
Time: 05:34:15 GMT, December 24, 2015


KFC proposal goes viral as social media offers to pay for couple's wedding
by Gerren Keith GaynorA man’s decision to propose to his girlfriend inside of a Kentucky Fried Chicken restaurant in South Africa has gone viral.
In a video posted on Twitter, the man is seen on bended knee asking for his lady’s hand in marriage. The couple is surrounded by KFC customers feverishly reacting to the surprise proposal.
MAN ACCIDENTALLY TRIPS A LITTLE GIRL WHILE PROPOSING TO HIS GIRLFRIEND
KFC South Africa reposted the video asking the public to help them identify the couple.
“Please help us find this beautiful couple,” the Twitter account posted on Thursday. “DM us any leads, there might be a Finger Lickin' Good surprise in it for you too … We love love.”
MAN BLASTED FOR 'HIJACKING' GIRLFRIEND'S GRADUATION WITH MARRIAGE PROPOSAL
Within hours, the couple was identified by KFC as Hector and Nonhlanhla.
Kateka Malobola, who posted the original video, said on Friday that the responses to the couple’s viral proposal have been overwhelming.
“It’s not even about the video, it’s about love,” he said. “The man ... I’m not as brave as he is. He went down on one knee in front of everybody at KFC. Everybody came running from outside that heard the screams from the cashiers and the patrons ... it’s genuine love.”
While some social media commentary poked fun at the man’s decision to choose KFC as the venue to pop the question, most reactions were positive.
FOLLOW US ON FACEBOOK FOR MORE FOX LIFESTYLE NEWS
“The beautiful moments don't have to cost much!” one person tweeted.
Another Twitter user wrote, “Oh my brought tears to my eyes, they look so in love!!”
“Never judge anyone's standard of living. This must be a dream come true, beginning of happy life,” one person tweeted.
CLICK HERE TO GET THE FOX NEWS APP
“That's why we don't find happiness, we focus on material things,” another person wrote.
The fanfare surrounding their unorthodox proposal garnered more than likes and retweets, however, as businesses and generous South Africans offered to help pay for the couple’s wedding, honeymoon and gifts.


Tori Huang
developer
&
engineer
Blog
About Me
Praise
Projects
Home
Thoughts, discoveries, and adventures
Find Blog Post (Search is work in progress):
Computer Memory - A High Level Overview, 2/20/16
Class vs. Prototype Based Programming, 2/11/16
Ruby Classes, 2/3/16
Ruby Enumerables, 1/30/16
Pair Programming, 1/26/16
Online Security, 1/21/16
Arrays and Hashes, 1/19/16
Positioning with CSS, 1/12/16
Using Git for the First Time, 1/3/16


To determine the type of response characteristic of an unknown system, it is often revealing to determine the system response to an impulse function. Suppose you have a measuring system with unknown characteristics, and you find it responds to an impulse as shown below:
Is this measuring system first-order or second-order? (Answer this before continuing to the next two questions.)


--- author: Capulet categories: app date: '2011-07-29 08:00:03' permalink: /2011/07/29/phonegap-1-0-released-today-at-phonegap-day-in-portland/ slug: phonegap-1-0-released-today-at-phonegap-day-in-portland status: publish title: PhoneGap 1.0 Released Today at PhoneGap Day in Portland type: post format: html categories: - News tags_old: - andre charland - brian leroux - phonegap - phonegap 1.0 ---
We're bubbling over with excitement about today's announcement: PhoneGap 1.0 launches today at PhoneGap Day in Portland! A giant thank you to the PhoneGap community who has generously contributed time and brain power to the cause. We'll be raising a glass to you today in Portland.
And now for the official announcement:
PhoneGap 1.0 Released Today at First-Ever PhoneGap Day in Portland Popular Open Source Mobile Development Framework Gets Upgrades Including More Access to Native Device APIs and Debugging Tools
Nitobi Inc., the creators of the popular PhoneGap mobile app development framework, releases PhoneGap 1.0 today at the first-ever PhoneGap Day in Portland, Oregon.
PhoneGap, an HTML5 platform, allows developers to use foundation web technology (HTML, CSS and JavaScript) to create native mobile applications. Using PhoneGap, developers can write their app once and deploy it to six major mobile platforms and app stores, including iOS, Android, BlackBerry, webOS, Bada and Symbian. PhoneGap has been widely recognized as a game-changer for mobile app development. The open source code is downloaded approximately 40,000 times every month, more than 600,000 times in total.
Today’s major release puts the focus on accessing native device APIs, which is new ground for the web. Other improvements include:
Today’s release also includes a new unifying bridge interface that makes adding platforms and platform extensions easy. Plus, developers will be pleased to see that the plugin development process has been simplified.
“Most of these new enhancements come from our community,” said Brian LeRoux, Senior Software Engineer at Nitobi and PhoneGap evangelist. “For instance, PhoneGap developers were calling for a consistent way to make plugins that would run on all major smartphone platforms and this release does that.”
“The community built up around PhoneGap is its greatest asset,” says Nitobi CEO Andre Charland. “The PhoneGap community identifies common pain points and works together to overcome them.” Contributors include Nitobi, hundreds of individual developers and a team of senior software engineers at IBM whose commitment and contributions to PhoneGap development has been a major benefit to the community.
IBM isn’t the only Fortune 500 to show interest in PhoneGap. Earlier this year, Adobe integrated PhoneGap into Dreamweaver so that developers can package apps with PhoneGap and launch iOS and Android emulators directly from within Dreamweaver. Other companies to adopt PhoneGap and its cross-platform philosophy include IBM, Alcatel-Lucent, Sabre, Cisco, Logitech and Time Warner.


Specify Scopes, Collections, and Mappings
{{(postCreateReplication.error | async)?.colMappingRules}}
{{(postSettingsReplications.error | async)?.colMappingRules}}
Scopes & Collections to Replicate
Checked scopes & collections can be mapped by clicking on the second name (ex: scopeName > NewName)
Use Migration Mode
{{(postCreateReplication.error | async)?.colMappingRules}}
{{(postSettingsReplications.error | async)?.colMappingRules}}


The reLuxe Ranch Hanging Tomato Vineyard
by Tasha
Since we had an absolutely despicable crop of tomatoes last year, we decided to try growing tomatoes upside-down in buckets this season. In a topsy-turvy world, full of environmental chaos, it’s never a bad idea to have multiple methods for performing the same function, a.k.a. redundancy. So, we’ll still put some tomatoes in beds to hedge our bets, but we’ve also added a new “Hanging Tomato Vineyard” to our garden line-up.
This kind of tomato growing is not new, but it is still considered a bit unconventional. If you’re considering trying it, here’s some info on pros/cons and what we’re doing.
CONS
1) You need a sturdy structure to support the weight of tomatoes grown in buckets and it must be sufficiently high-off the ground to allow for plants vining habit. This requires work and money - always a con in my book.
In our case, we put 4.5” diameter fence posts a little over 2’ in the ground at about 7’10” apart. We then topped the posts with 8’ weather-treated 2” x 4” boards. After installing heavy duty stainless steel hooks and hanging empty buckets on those hooks, we realized we needed more reinforcement. So we bought some longer 2”x 4” boards to cross over the joints on the first layer of boards. This seemed to do the trick and added stability (even when the buckets were full and watered).
Now, when I say “we” - I really mean Matt ( my big, strong, hunky, wonderfully capable man). He carefully leveled everything and made sure the posts were not going to pop-out of the ground. He mounted the 2 x 4’s and hooks, etc. I probably could have done this (spending ten times as long and cussing up a blue streak), but if you have a big strong, mathematically-minded man around, I highly recommend you put this one on his honey-do list! Thank you Matt!
**2) You will have to water a lot more, particularly in hot weather. **
Even though the tomatoes are growing down instead of up, this is essentially the same as growing tomatoes in a container and that means frequent watering since there is a limit to how far the roots can go in search of water. To help retain moisture in the soil, I made up my own potting mix. I had twenty buckets to plant so it took me four wheelbarrows of “planting medium” (to use the PC term) to fill them all. My particular mix was about 40% good old fashioned North Carolina red clay soil (naturally micronutrient rich), 40% organic matter (leaf and manure compost), and 20% peat moss. I also threw in about fifteen dozen crushed egg shells (saved from breakfast for the last couple months) since tomatoes love calcium. When I get my next batch of hardwood mulch, I’ll also top the buckets off with about an inch of mulch to help retain moisture.
I only filled the buckets about 60% full to start because I plan to throw in a handful of compost/worm castings in each bucket before watering so that as the water trickles through the compost, it will act as a compost tea for the roots. The compost layer will get thicker as the season progresses and days get hotter. By doing it this way, I ensure my nutrients don’t all leach out at once and I retain moisture when the tomatoes need it most. (This is all theoretical speculation on my part at this point, but I’ll include a follow up post with results at the end of the season.)
Fun Factoid: I didn’t list buying soil mix as a con because even if you stick these suckers in the ground - you better planning on heavily amending your soil if you want a fine tomato. Amending ground soil may be a bit cheaper than buying all new soil, but it is often more work than just making or buying your own mix, so I considered soil preparation as a “net even” on the pro/con scale.
**3) This isn’t the best answer for them giant ‘maters. **
If you want five pound Cherokee purples, you probably want to stick with traditional staking. From what I’ve read, the really big suckers would still need support even if they are dangling upside down on the vine. We’re going with Manalucie this go round because they are somewhat disease resistant and grow well in our super hot weather. They are usually medium-sized, but some can get big in the right conditions. So if necessary, we may have to harvest early and ripen off the vine.
PROS (I think…)
Once you’ve addressed the stuff in the cons - you’ve got good support, you have a watering plan, and you are growing the right variety, then here’s the good news:
- You don’t have to stake.
- Pruning is a piece of cake.
- Fertilizing is easy with the compost method covered under the cons.
- You will have fewer or easier to deal with pest/disease problems.
- You’ll have great air circulation, so your tomatoes will ripen faster.
- Harvesting will be like picking an apple instead of fighting through a nest of snakes.
- It looks cool and adds vertical interest and space to your garden. (You can plant your basil below to maximize space.)
So, if you want to do this yourself, put on your pink crocs and get started. Here’s how.
Stuff You Need
- Your favorite potting soil mix
- Bucket
- Drill and a 1.5” hole driller paddle-thingy
- Tomato seedling (well-rooted 2”-3” pot size is about right)
- 6” scrap of weed mat
**Basic Steps **
Put a hole in the bottom of the bucket. When you start to bust through the plastic, the drill will try to rip your arm off. So, I recommend putting the bucket on the ground and holding it in place with one well-shod foot. Use two hands to hold the drill and exert as much downward pressure as you can.
Cut a slit in your weed mat scrap. Get your tomato seedling out of the pot and wrap the weed mat around it. Basically, it’s like putting the skirt under a Christmas tree, except you do it in your hands, and you hold the vine down so the dirt and roots gets cradled in the weed mat.
Note: I start my own seedlings in our greenhouse in recycled half gallon milk boxes (eight per box). Then I just rip one end of the box open and peel out a seedling, keeping as much of the root structure intact as possible. My roots get loosened as I separate them from the others in the box, but you may need to loosen your roots at the bottom if they are individually potted.
Now you have to fit the tomato vine through the hole in the bucket. As you do this, be gentle with the leaves so they come through intact. Also make sure the weed mat covers the hole and stays crossed over on the slitted side.
If you are smart, you’ll put the bucket on a two cinder blocks (leaving space in the middle for the vine to hang down) and take your time doing this.
If you are me, you will wedge the bucket between your knees then push it against the wheelbarrow. You will then quickly (because your quadriceps are now burning) shove the seedling in, fill the bucket 60 % full with planting medium, and try not to fall over or injure your back (and simultaneously try to take pictures so I can show you what I am doing.)
If you survive potting, hang that sucker. And water it good. You don’t want the weight of the water to push the weedmat and seedling out the hole, so use a watering can and water slowly. I ended up using about a gallon per bucket. But I poured, waited, then poured again. When I saw a few droplets roll down the vines, I knew I’d watered enough. Once you’re tomatoes have a good system, you can water more haphazardly, but you want to pour slowly for the first couple weeks.
Tip: If you are like me, and prefer not to advertise that you were forced to buy your utility buckets from the mega-hardware store (because no one else had the quanities you need at the price you could afford) make sure you put the non-logoed most-visible side out before you water. These suckers get heavy once that soil draws in all that moisture.
Bonus! When you are done, you can take all that confetti you made while drilling holes and have an “I did it” party!
Subscribe via RSS


To add a new access point:
AccessPointCreateEntry()
routine to create the access point. To create an internet access point, use the syntax:newID = AccessPointCreateEntry( 0, APT_INTERNET );
AccessPointCreateEntry()
, set the appropriate properties for the access point.


contact
Got a project? Want to collaborate? Or want to grab a beer?
Contact me using this form or via one of media channels listed at the bottom.
I'll get back to you as soon as I can
Got a project? Want to collaborate? Or want to grab a beer?
Contact me using this form or via one of media channels listed at the bottom.
I'll get back to you as soon as I can


| Package | Description |
|---|---|
| authoringenvironment.model | |
| gameengine.controller | |
| gameengine.model | |
| gameengine.model.Actions | |
| gameengine.model.Triggers | |
| gameplayer.view | |
| usecases |
| Class and Description |
|---|
| IRule
This interface defines the public methods for Rule objects.
|
| Class and Description |
|---|
| Actor
This class defines the logic for an Actor object.
|
| ITrigger
This interface defines the public methods for Trigger objects.
|
| PhysicsEngine
Physics Engine Class
Handles calculating/assigning new positions based on positional attributes and movement vectors
Receives Actor object via movement specific methods (ie moveRight, jump)
These methods then apply a set force that affects and updates the Actor's
position and velocity variables
|
| Class and Description |
|---|
| Actor
This class defines the logic for an Actor object.
|
| Attribute |
| AttributeType |
| IActor
This interface defines a limited subset of Actor functionality.
|
| IRule
This interface defines the public methods for Rule objects.
|
| ITrigger
This interface defines the public methods for Trigger objects.
|
| PhysicsEngine
Physics Engine Class
Handles calculating/assigning new positions based on positional attributes and movement vectors
Receives Actor object via movement specific methods (ie moveRight, jump)
These methods then apply a set force that affects and updates the Actor's
position and velocity variables
|
| Class and Description |
|---|
| Actor
This class defines the logic for an Actor object.
|
| AttributeType |
| IAction
This interface defines the public methods that each Action subclass will have.
|
| Class and Description |
|---|
| Actor
This class defines the logic for an Actor object.
|
| IActor
This interface defines a limited subset of Actor functionality.
|
| ITrigger
This interface defines the public methods for Trigger objects.
|
| Class and Description |
|---|
| Actor
This class defines the logic for an Actor object.
|
| IActor
This interface defines a limited subset of Actor functionality.
|
| Class and Description |
|---|
| Actor
This class defines the logic for an Actor object.
|


Enter a zipcode and we'll tell you what type of beer you should be drinking based on your current weather!


Welcome to Sea Scavenger!
What is a circular economy? We're glad you asked!
In a circular economy, nothing goes to waste. Instead, when goods reach the end of their life, they are remanufactured into something new.
Your task in this game is to recover plastic waste from the coasts of countries around the world so the items can be remanufactured.
- For each turn, you will be given a mission to recover a specific type of plastic waste.
- You then choose the country your team will recover the plastic from to achieve the mission.
- If there is enough of that type of plastic waste at that location, you will succeed and get a new mission.
- If you don't retrieve enough waste, the game is over.


OREKIT
1. Purpose
OREKIT library is a low level library for space mechanics projects. It is
implemented in the JAVA language.
OREKIT project was initiated by CS with the following goals in mind:
- provide a common base layer for space projects
- support both quick developments with loose requirements and complex
projects with rich physical modeling, fine customization, and high accuracy
- be user-extensible through clear and as simple as possible architecture
- use unified interfaces to allow models and algorithms switching with almost no effort
- provide both basic and rich models that can be plugged interchangeably to ease
applications validation
- separate models configuration from models usage to hide away complexity and keep
caller code simple
- support both development of standalone and embedded applications (web services,
plugins, scripting frameworks ...)
- use up-to-date techniques for low cost development and maintenance
- remove platforms and system dependencies and leverage environment-hell
(environment variables, dynamic libraries versions, operating system,
filesystem layout ...)
2. Features
Orekit can be used for many purposes, from simple geometrical or orbital tools
up to complex orbits propagators with several perturbing forces, maneuvers and
discrete events. Here is a short list of the features offered by the library:
- Time
- high accuracy absolute dates
- time scales (TAI, UTC, GPS, TCG, TT ...)
- transparent handling of leap seconds
- Geometry
- frames hierarchy supporting fixed and time-dependent (or telemetry-dependent) frames
- predefined frames (EME2000/J2000, GCRF, ITRF2005 and intermediate frames, Veis, topocentric,
tnw and qsw local orbital frames, Moon, Sun, planets, solar system barycenter, Earth-Moon barycenter)
- user extensible (used operationally in real time with a set of about 60 frames on several spacecrafts)
- transparent handling of IERS Earth Orientation Parameters
- transparent handling of JPL DE 405 and DE 406 ephemerides
- transforms including kinematic combination effects
- composite transforms reduction and caching for efficiency
- extensible central body shapes models (with predefined spherical and ellipsoidic shapes)
- cartesian and geodesic coordinates, kinematics
- Spacecraft state
- cartesian, elliptical keplerian, circular and equinoctial parameters
- Two-Lines Elements
- transparent conversion between all parameters
- automatic binding with frames
- attitude state and derivative
- mass management
- Propagation
- analytical propagation models (Kepler, Eckstein-Heschler, SDP4/SGP4 with 2006 corrections)
- numerical propagators
- customizable force models
- central attraction
- gravity models (automatic reading of SHM (for Eigen models) and EGM formats potential files, even compressed)
- atmospheric drag (DTM2000, Jacchia-Bowman 2006 and simple exponential models)
- third body attraction (with data for Sun, Moon and all solar systems planets)
- radiation pressure with eclipses
- multiple maneuvers
- state of the art ODE integrators (adaptive stepsize with error control,
continuous output, switching functions, G-stop, step normalization ...)
- can be used in master mode (program drives integration), slave mode (integrator
drives program) or unattended mode (all intermediate results solved and
navigation feature enabled, to use the model as if it was an analytical model,
ideal for search and iterative algorithms)
- serialization mechanism to store complete results on persistent storage for later use
- tabulated ephemerides
- file based
- memory based
- integration based
- unified interface above analytical/numerical/tabulated propagators for easy
switch from coarse analysis to fine simulation with one line change
- all propagators can be used in several different modes
- slave mode: propagator is driven by calling application
- master mode: propagator drives application callback functions
- ephemeris generation mode: all intermediate results are stored during
propagation and provided back to the application which can navigate at will
through them, effectively using the propagated orbit as if it was an
analytical model, even if it really is a numerically propagated one, which
is ideal for search and iterative algorithms
- handling of discrete events during integration
(models changes, G-stop, simple notifications ...)
- predefined discrete events
- ascending and descending node crossing
- apogee and perigee crossing
- raising/setting with respect to a ground location
(with customizable triggering elevation)
- altitude crossing
- date
- impulse maneuvers occurrence
- Attitude
- extensible attitude evolution models
- predefined laws
- central body related attitude
(nadir pointing, center pointing, target pointing,
yaw compensation, yaw-steering)
- orbit referenced attitudes (LOF aligned, offset on all axes)
- space referenced attitudes (inertial, celestial body pointed, spin stabilized)
3. Dependency
OREKIT has only one dependency: the commons-math
open-source library. This library provides mathematical tools for many purposes: geometry,
polynomial equations, differential equations, and more... It is distributed under the
business-friendly Apache Software License version 2.0.
OREKIT is based on two commons-math packages:
- {@link org.apache.commons.math.geometry}, which provides very useful objects as vectors
and rotations (internally represented by quaternions)
- {@link org.apache.commons.math.ode}, which provides numerical solutions to solve
Ordinary Differential Equations (ODE).
The use of commons-math is hidden in OREKIT as much as possible so users don't
need to fully master this library. If they wish, they can limit themselves to understanding
the simple classes {@link org.apache.commons.math.geometry.Vector3D} and
{@link org.apache.commons.math.geometry.Rotation}, and the interface
{@link org.apache.commons.math.ode.FirstOrderIntegrator}.
@author Luc Maisonobe
@author Fabien Maussion
@author Véronique Pommier-Maurussane
@author Guylaine Prat


CPF interest rates to stay unchanged for Q1, 2020
by Cheow Sue-AnnThe interest rates that can be earned on the various Central Provident Fund (CPF) accounts will remain unchanged between January and March 2020, the CPF Board and Housing Board said in a joint press release yesterday.
CPF members will continue to earn interest rates of up to 3.5 per cent a year on their Ordinary Account (OA) money, and up to 5 per cent a year on their Special and MediSave accounts money in the first quarter of 2020.
The CPF board said that the interest rates include an extra 1 per cent interest paid on the first $60,000 of a member's combined balances.
Members aged 55 and above will also earn an additional 1 per cent extra interest on the first $30,000 of their combined balances.
This is on top of the extra 1 per cent interest that is earned on the first $60,000 of their combined balances.
BASIC HEALTHCARE SUM RAISED
As a result, members aged 55 and above will earn up to 6 per cent interest a year on their retirement balances.
The extra interest received on the OA will go into the member's Special Account (SA) or Retirement Account (RA) to enhance his or her retirement savings. The interest rate on SA and RA will also remain unchanged.
From January next year, the Basic Healthcare Sum (BHS) will be raised from $57,200 to $60,000 for Central Provident Fund (CPF) members below age 65.
The BHS is the estimated savings required for basic subsidised healthcare needs in old age, and is adjusted yearly for members below 65 years of age to keep pace with the growth in MediSave withdrawals, said the CPF board in a press release yesterday.
Once members reach the age of 65, their BHS will be fixed for the rest of their lives.


We've sent details to {{values.email}}
Download confirmation
Application reference: PEX 319 825 680X
Before we can work on your application, you need to:
Sign in to check who can do this and provide their details. You'll need your application reference: PEX 319 825 680X
We can only receive your documents after your identity has been confirmed. We'll let you know when and where to send them.
Sign in


logistic-metadata-example.Rmd
A simple, example forecast of population growth of two interacting species
========================================================
To illustrate the application of the forecast standard, we’ll consider the classic Lotka-Volterra population growth model. To keep this first example simple, we’ll only consider two species and two uncertainties - an additive process error, which converts this to a stochastic Lotka-Volterra, and an observation error. We’ll propagate uncertainty by running multiple ensembles. To illustrate the ability of the output format to accommodate spatial dimensions, we’ll run the model at multiple depths in a water column (e.g. lake or ocean) but those depths are not interacting – we know this isn’t realistic, but we want to keep things simple. Overall, this gives us the following dimensions
forecast_start_time = as.Date("2001-03-04") ## start date of our forecast
n_time <- 30
times = seq(from=forecast_start_time,by="1 day",length=n_time)
depths <- c(1, 3, 5)
n_depths <- length(depths)
n_ensembles <- 10
ensembles <- seq_len(n_ensembles)
species <- c("species_1","species_2")
n_species <- length(species)
obs_dim <- 2 ## 1 = latent state
## 2 = latent state + observation error
= datetime.date(2001, 3, 4)
forecast_start_time = 30
n_time = [forecast_start_time + datetime.timedelta(days = x) for x in range(n_time)]
times
= [1, 3, 5]
depths = len(depths)
n_depths
= 10
n_ensembles = list(range(n_ensembles))
ensembles
= ["species_1", "species_2"]
species = len(species)
n_species
= 2 ## 1 = latent state, 2 = latent_state + observation error obs_dim
Next we’re going to assume fixed parameters and initial conditions, set up storage for our forecast output (which we see has 5 dimensions), and then forward simulate the populations
## parameters for species_1 and species_2
r <- c(1, 3)
K <- c(10, 20)
alpha <- c(0.2, 0.3)
## process error
process_sd <- 0.01
## observation error
obs_sd <- c(0.5,0.2)
## initial conditions
n0 <- 0.5
## forecast output storage
n <- array(NA,dim = c(n_time, n_depths, n_ensembles, obs_dim,2)) ## last dim is species
n[1,,,,] <- n0
## forecast flag
forecast <- rep(as.integer(0), n_time) ## this code indicated a hindcast
## data assimilation flag
data_assimilation <- rep(as.integer(0), n_time) ## this code indicates a 'free-run' that didn't assimilate new data
## forward simulation
for(t in 2:n_time){
for(depth in 1:n_depths){
for(ens in 1:n_ensembles){
## predict latent state
n_curr <- n[t-1,depth,ens,1,] ## current state
n[t, depth, ens,1,1] <- n_curr[1] +
r[1]*n_curr[1]*(1-((n_curr[1] +
alpha[1]*n_curr[2])/K[1])) + rnorm(1, 0, process_sd)
n[t, depth, ens,1,2] <- n_curr[2] +
r[2]*n_curr[2]*(1-((n_curr[2] +
alpha[2]*n[1])/K[2])) + rnorm(1, 0, process_sd)
## predict observed values
n[t,depth,ens,2,] = rnorm(2,n[t,depth,ens,1,],obs_sd)
}
}
}
= [1, 3]
r = [10, 20]
K = [0.2, 0.3]
alpha
= 0.01
process_sd = [0.5, 0.2]
obs_sd
= 0.5
n0
= np.zeros((n_time, n_depths, n_ensembles, obs_dim, n_species))
n 0,:,:,:,:] = n0
n[
= np.zeros((n_time), dtype=int)
forecast = np.zeros((n_time), dtype=int)
data_assimilation
for t in range(1, n_time):
for depth in range(n_depths):
for ens in range(n_ensembles):
# predict latent state
= n[t-1,depth,ens,0,:]
n_curr 0, 0] = n_curr[0] + \
n[t, depth, ens, 0] * n_curr[0] * \
r[1 - ((n_curr[0] + alpha[0]*n_curr[1]) / K[0])) + \
(1) * process_sd
np.random.randn(0, 1] = n_curr[1] + \
n[t, depth, ens, 1] * n_curr[1] * \
r[1 - ((n_curr[1] + alpha[1]*n_curr[0]) / K[1])) + \
(1) * process_sd
np.random.randn(# predict observed values
1,:] = n[t,depth,ens,0,:] + np.random.randn(2) * obs_sd n[t,depth,ens,
Here’s a simple visualization of our ensemble forecast at one depth
plot(times,n[,1,1,1,1],ylim=range(n),ylab="Population Density",type='l')
for(s in seq_along(species)){ ##species
for(e in ensembles){
lines(times,n[,1,e,1,s],col=s) ## latent
points(times+runif(n_time,-0.12,0.12),n[,1,e,2,s],col=s,cex=0.35) ## pseudo-obs w/ jitter
}
}
legend("bottomright",legend=species,col = seq_along(species),lty = 1)
0,0,0,0], "-")
plt.plot(times, n[:,= ["r", "b"]
colors for s in range(n_species):
for e in range(n_ensembles):
0,e,0,s], "-", color=colors[s])
plt.plot(times, n[:,0,e,1,s], "+", color=colors[s])
plt.plot(times, n[:,= [plt.Line2D([0], [0], color=colors[x]) for x in range(n_species)]
leg_lines = [f"Species {x}" for x in range(n_species)]
leg_labs
plt.legend(leg_lines, leg_labs)"Time")
plt.xlabel("Population Density")
plt.ylabel( plt.show()
Because netCDF is a self-documenting format we’re going to start by defining some forecast identifiers (which we’ll also later use in the metadata)
forecast_project_id
identifies forecasts coming from a
single project and is used to link forecasts different model versions.
Examples might include a project Github repository or a team name.
forecast_model_id
is updated each time the forecast code
is modified (e.g. model structure, model calibration, forecast
workflow). Examples might be a DOI, version number, or Github hash.
Results from a single forecast_model_id are considered comparable.
forecast_iteration_id
represents a unique ID for each
forecast run. Examples might be a start time or database ID.
For example, if you have a forecast code base on GitHub and launch a forecast from that code that runs daily for 365 days, then there will be one forecast_project_id and 365 forecast_iteration_ids. A paper analyzing the forecasts would cite the forecast_project_id.
Once we have our ID’s defined, we’re going to use
ncdim_def
to define the dimensions that our output
variables will have
## Set dimensions
timedim <- ncdim_def("time", ## dimension name
units = paste('days since',forecast_start_time),
## size of timestep, with units and start date
vals = as.numeric(times - forecast_start_time),
## sequence of values that defines the dimension.
## netCDF expresses time dimensions relative to a
## specified start date, in this case forecast_start_time
longname = 'time')
## descriptive name
depthdim <- ncdim_def("depth",
units = "meters",
vals = depths,
longname = 'Depth from surface')
parmdim <- ncdim_def("parameter",
units = "",
vals = ensembles,
longname = 'ensemble member')
obsdim <- ncdim_def("obs_flag",
units = "",
vals = 1:obs_dim,
longname = "observation error flag. 1 = latent state, 2 = w/ obs error")
## quick check that units are valid
udunits2::ud.is.parseable(timedim$units)
## [1] TRUE
udunits2::ud.is.parseable(depthdim$units)
## [1] TRUE
udunits2::ud.is.parseable(parmdim$units)
## [1] TRUE
udunits2::ud.is.parseable(obsdim$units)
## [1] TRUE
Note that unlike R, the Python interface expects us to create the output NetCDF file first before populating it with output.
= tempfile.NamedTemporaryFile(suffix=".nc")
ncfile = netCDF4.Dataset(ncfile.name, mode='w')
ncout
= ncout.createDimension("time", n_time)
timedim = ncout.createVariable("time", "f4", "time")
timevar = f"days since {forecast_start_time}"
timevar.units = [(t - forecast_start_time).days for t in times]
timevar[:]
= ncout.createDimension("depth", n_depths)
depthdim = ncout.createVariable("depth", "f4", "depth")
depthvar = "meters"
depthvar.units = depths
depthvar[:]
= ncout.createDimension("parameter", n_ensembles)
parmdim = ncout.createVariable("parameter", "i4", "parameter")
parmvar = ""
parmvar.units = ensembles
parmvar[:]
= ncout.createDimension("obs_flag", obs_dim)
obsdim = ncout.createVariable("obs_flag", "i4", "obs_flag")
obsvar = ""
obsvar.units = list(range(obs_dim)) obsvar[:]
Once we’ve defined our dimensions, we can then define the metadata
about our variables using ncvar_def
fillvalue <- 1e32 ## missing data value
#Define variables
def_list <- list()
def_list[[1]] <- ncvar_def(name = "species_1",
units = "number of individuals",
dim = list(timedim, depthdim, parmdim, obsdim),
missval = fillvalue,
longname = '<scientific name of species 1>',
prec="single")
def_list[[2]] <- ncvar_def(name = "species_2",
units = "number of individuals",
dim = list(timedim, depthdim, parmdim, obsdim),
missval = fillvalue,
longname = '<scientific name of species 2>',
prec="single")
def_list[[3]] <- ncvar_def(name = "forecast",
units = "integer",
dim = list(timedim),
missval = fillvalue,
longname = 'EFI standard forecast code. 0 = hindcast',
prec="single")
def_list[[4]] <- ncvar_def(name = "data_assimilation",
units = "integer",
dim = list(timedim),
missval = fillvalue,
longname = 'EFI standard data assimilation code. 0 = no data',
prec="single")
= ncout.createVariable("species_1", "f4", ("time", "depth", "parameter", "obs_flag"))
spp1nc = "number of individuals"
spp1nc.units = "<scientific name of species 1>"
spp1nc.longname
= ncout.createVariable("species_2", "f4", ("time", "depth", "parameter", "obs_flag"))
spp2nc = "number of individuals"
spp2nc.units = "<scientific name of species 2>"
spp2nc.longname
= ncout.createVariable("forecast", "i4", ("time"))
forecastnc = "integer"
forecastnc.units = "EFI standard forecast code. 0 = hindcast"
forecastnc.longname
= ncout.createVariable("data_assimilation", "i4", ("time"))
danc = "integer"
danc.units = "EFI standard data assimilation code. 0 = no data" danc.longname
Finally, we’ll now create our netCDF file and add our outputs and global metadata to the file
## file name
ncfname <- "logistic-forecast-ensemble-multi-variable-space-long.nc"
## open your netCDF file
ncout <- nc_create(ncfname,def_list,force_v4=T)
## fill in our output data
ncvar_put(ncout,def_list[[1]] , n[, , , ,1 ]) ## species 1
ncvar_put(ncout,def_list[[2]] , n[, , , ,2 ]) ## species 2
ncvar_put(ncout,def_list[[3]] , forecast) ## forecast flag
ncvar_put(ncout,def_list[[4]] , data_assimilation) ## data_assimilation flag
## Global attributes (metadata)
ncatt_put(ncout,0,"forecast_project_id", as.character(forecast_project_id),
prec = "text")
ncatt_put(ncout,0,"forecast_model_id",as.character(forecast_model_id),
prec = "text")
ncatt_put(ncout,0,"forecast_iteration_id",as.character(forecast_iteration_id),
prec = "text")
nc_close(ncout) ## make sure to close the file
Recall: We already created the file above.
# Write data to file
= n[:,:,:,:,0]
spp1nc[:,:,:,:] = n[:,:,:,:,1]
spp2nc[:,:,:,:] = forecast
forecastnc[:] = data_assimilation
danc[:]
# Set global attributes (metadata)
= forecast_project_id
ncout.forecast_project_id = forecast_model_id
ncout.forecast_model_id = forecast_iteration_id
ncout.forecast_iteration_id
ncout.close()
Convert to a flat file format (CSV) with one column for each variable and all ensemble members saved
## wrangle data from an array into a long format
df_combined <- reshape2::melt(n,varnames=c("time","depth","parameter","obs_flag","species")) %>%
pivot_wider(id_cols = 1:4,names_from = "species",names_prefix = "species_",values_from = "value") %>%
pivot_longer(cols = starts_with("species"),names_to = "variable",values_to = "prediction") %>%
mutate(time = times[time]) %>%
mutate(depth = depths[depth]) %>%
right_join(tibble(time=times,forecast=forecast,data_assimilation = data_assimilation))
## Joining, by = "time"
head(df_combined,n=10)
## # A tibble: 10 × 8
## time depth parameter obs_flag variable prediction forecast
## <date> <dbl> <int> <int> <chr> <dbl> <int>
## 1 2001-03-04 1 1 1 species_1 0.5 0
## 2 2001-03-04 1 1 1 species_2 0.5 0
## 3 2001-03-05 1 1 1 species_1 0.984 0
## 4 2001-03-05 1 1 1 species_2 1.95 0
## 5 2001-03-06 1 1 1 species_1 1.82 0
## 6 2001-03-06 1 1 1 species_2 7.16 0
## 7 2001-03-07 1 1 1 species_1 3.04 0
## 8 2001-03-07 1 1 1 species_2 20.8 0
## 9 2001-03-08 1 1 1 species_1 3.88 0
## 10 2001-03-08 1 1 1 species_2 17.8 0
## # … with 1 more variable: data_assimilation <int>
write.csv(df_combined,
file = "logistic-forecast-ensemble-multi-variable-multi-depth.csv")
** this code needs updating for the new format**
= ["time", "depth", "ensemble", "obs_flag", "species"]
n_names = pd.MultiIndex.from_product([range(s) for s in n.shape], names=n_names)
n_index = pd.DataFrame({"pop": n.flatten()}, index = n_index)["pop"]
df
= df.unstack("species").reset_index()
df_wide "time"] = [times[x] for x in df_wide["time"]]
df_wide["depth"] = [depths[x] for x in df_wide["depth"]]
df_wide[={0: "Species_1", 1: "Species_2"}, inplace=True)
df_wide.rename(columns
= pd.DataFrame({"time": times, "forecast": forecast, "data_assimilation": data_assimilation})
meta_df
= df_wide.merge(meta_df, on="time", how="right")
df_combined df_combined.head()
## time depth ensemble ... Species_2 forecast data_assimilation
## 0 2001-03-04 1 0 ... 0.5 0 0
## 1 2001-03-04 1 0 ... 0.5 0 0
## 2 2001-03-04 1 1 ... 0.5 0 0
## 3 2001-03-04 1 1 ... 0.5 0 0
## 4 2001-03-04 1 2 ... 0.5 0 0
##
## [5 rows x 8 columns]
= tempfile.NamedTemporaryFile(suffix=".csv")
out_csv df_combined.to_csv(out_csv.name)
Convert to a flat file format (CSV) with forecast distributions saved
## calculate summary statistics across ensemble members and output variables
dfs <- df_combined %>% add_column(family="normal") %>%
group_by(time, depth,family,obs_flag,variable,forecast,data_assimilation) %>%
summarize(mu = mean(prediction),
sigma = sd(prediction)) %>%
pivot_longer(8:9,names_to="parameter",values_to = "predictions") %>%
relocate(parameter,.after = family) %>%
relocate(predictions,.after=variable)
## `summarise()` has grouped output by 'time', 'depth', 'family', 'obs_flag',
## 'variable', 'forecast'. You can override using the `.groups` argument.
head(dfs,n=10)
## # A tibble: 10 × 9
## # Groups: time, depth, family, obs_flag, variable, forecast [5]
## time depth family parameter obs_flag variable predictions forecast
## <date> <dbl> <chr> <chr> <int> <chr> <dbl> <int>
## 1 2001-03-04 1 normal mu 1 species_1 0.5 0
## 2 2001-03-04 1 normal sigma 1 species_1 0 0
## 3 2001-03-04 1 normal mu 1 species_2 0.5 0
## 4 2001-03-04 1 normal sigma 1 species_2 0 0
## 5 2001-03-04 1 normal mu 2 species_1 0.5 0
## 6 2001-03-04 1 normal sigma 2 species_1 0 0
## 7 2001-03-04 1 normal mu 2 species_2 0.5 0
## 8 2001-03-04 1 normal sigma 2 species_2 0 0
## 9 2001-03-04 3 normal mu 1 species_1 0.5 0
## 10 2001-03-04 3 normal sigma 1 species_1 0 0
## # … with 1 more variable: data_assimilation <int>
write.csv(dfs, file = "logistic-forecast-summary-multi-variable-multi-depth.csv")
= [col for col in df_combined.columns if not "Species" in col]
keep_cols = df_combined.melt(id_vars=keep_cols, var_name="species")
df_long
= df_long\
dfs_wide "time", "depth", "obs_flag", "species", "forecast", "data_assimilation"])\
.groupby([
.agg(= ("value", np.mean), sd = ("value", np.std),
mean = ("value", lambda x: np.quantile(x, 0.025)),
Conf_interv_025 = ("value", lambda x: np.quantile(x, 0.975)),
Conf_interv_975 \
)\
.reset_index()
.melt(= ["time", "depth", "obs_flag", "forecast",
id_vars "data_assimilation", "species"],
= ["mean", "sd", "Conf_interv_025", "Conf_interv_975"],
value_vars = "statistic"
var_name
)
= dfs_wide.pivot(
dfs = ["time", "depth", "obs_flag", "forecast",
index "data_assimilation", "statistic"],
="species",
columns= "value"
values
).reset_index()
dfs.head()
## species time depth obs_flag ... statistic Species_1 Species_2
## 0 2001-03-04 1 0 ... Conf_interv_025 0.5 0.5
## 1 2001-03-04 1 0 ... Conf_interv_975 0.5 0.5
## 2 2001-03-04 1 0 ... mean 0.5 0.5
## 3 2001-03-04 1 0 ... sd 0.0 0.0
## 4 2001-03-04 1 1 ... Conf_interv_025 0.5 0.5
##
## [5 rows x 8 columns]
= tempfile.NamedTemporaryFile(suffix=".csv")
out_summary dfs.to_csv(out_summary.name)
Let’s begin by documenting the metadata of the forecast output data
table itself, which we’ll do using EML’s dataTable
entity.
In this example we’ll assume we’re working with format 2 (ensemble CSV),
though most of the metadata would be identical for all three
formats.
To start, the attributes
table stores the basic metadata
about the variable names and units.
## define variable names, units, etc
## in practice, this might be kept in a spreadsheet
attributes <- tibble::tribble(
~attributeName, ~attributeDefinition, ~unit, ~formatString, ~numberType, ~definition,
"time", "[dimension]{time}", "year", "YYYY-MM-DD", "numberType", NA,
"depth", "[dimension]{depth in reservior}", "meter", NA, "real", NA,
"ensemble", "[dimension]{index of ensemble member}", "dimensionless", NA, "integer", NA,
"obs_flag", "[dimension]{observation error}", "dimensionless", NA, "integer", NA,
"species_1", "[variable]{Pop. density of species 1}", "numberPerMeterSquared", NA, "real", NA,
"species_2", "[variable]{Pop. density of species 2}", "numberPerMeterSquared", NA, "real", NA,
"forecast", "[flag]{whether time step assimilated data}", "dimensionless", NA, "integer", NA,
"data_assimilation", "[flag]{whether time step assimilated data}", "dimensionless", NA, "integer", NA
)
## note: EML uses a different unit standard than UDUNITS. For now use EML. EFI needs to provide a custom unitList.
attributes
## # A tibble: 8 × 6
## attributeName attributeDefinition unit formatString numberType definition
## <chr> <chr> <chr> <chr> <chr> <lgl>
## 1 time [dimension]{time} year YYYY-MM-DD numberType NA
## 2 depth [dimension]{depth … meter NA real NA
## 3 ensemble [dimension]{index … dime… NA integer NA
## 4 obs_flag [dimension]{observ… dime… NA integer NA
## 5 species_1 [variable]{Pop. de… numb… NA real NA
## 6 species_2 [variable]{Pop. de… numb… NA real NA
## 7 forecast [flag]{whether tim… dime… NA integer NA
## 8 data_assimilation [flag]{whether tim… dime… NA integer NA
attrList <- set_attributes(attributes,
col_classes = c("Date", "numeric", "numeric","numeric",
"numeric","numeric", "numeric","numeric"))
Note that the EFI standard extends the EML
attibuteDefinition
to include a [variable_type] and
{variable_definition}. The options for [variable_type] include: *
dimension * variable = output variable * diagnostic = variable output
purely for diagnostic purposes * observation = data that is or could be
compared to an output_variable * obs_error * flag * initial_condition *
driver * parameter * random_effect * process_error
We then link the attribute information with the info about a particular file
## sets metadata about the file itself (name, file type, size, MD5, etc)
physical <- set_physical("logistic-forecast-ensemble-multi-variable-multi-depth.csv",
recordDelimiter='\n')
## Automatically calculated file size using file.size("logistic-forecast-ensemble-multi-variable-multi-depth.csv")
## Automatically calculated authentication size using digest::digest("logistic-forecast-ensemble-multi-variable-multi-depth.csv", algo = "md5", file = TRUE)
## set metadata for the file as a whole
dataTable <- eml$dataTable(
entityName = "forecast", ## this is a standard name to allow us to distinguish this entity from
entityDescription = "Forecast of population size using a depth specific model",
physical = physical,
attributeList = attrList)
Here entityName = "forecast"
is a standard name within
the EFI standard to allow us to distinguish this entity from metadata
about parameters, drivers, etc.
There’s a lot more optional terminology that could be exploited here
– for instance, the specification lets us define different missing value
codes (and explanations) for each column, and allows us to indicate
precision
, minimum
and
maximum
.
Note that physical
type can document almost any formats
as well, including NetCDF etc. A NetCDF file would still document the
variables measured in much the same way regardless of the underlying
representation.
Now that we’ve documented the actual data.frame itself, we can add additional metadata to the record describing our forecast, which is essential for citing, discovering, and interpreting the result. We start with some authorship information.
Set Taxonomic, Temporal, and Geographic Coverage. (Look, apparently we’re modeling population densities of Gloeotrichia echinulata and Anabaena circinalis cyanobacterium in Lake Sunapee, NH, USA)
taxa <- tibble::tribble(
~Genus, ~Species,
"Gloeotrichia", "echinulata",
"Anabaena", "circinalis")
coverage <-
set_coverage(begin = first(times),
end = last(times),
sci_names = taxa,
geographicDescription = "Lake Sunapee, NH, USA ",
west = -72.15, east = -72.05,
north = 43.48, south = 43.36)
Our dataset needs an abstract describing what this is all about.
abstract_text <- system.file("extdata", "abstract.md", package="EFIstandards", mustWork = TRUE)
Next, we’ll combine these various bits to document the output dataset as a whole
dataset = eml$dataset(
title = "A very simple Lotka-Volterra forecast",
creator = me,
contact = list(references="https://orcid.org/0000-0003-1282-7825"),
pubDate = forecast_start_time,
intellectualRights = "http://www.lternet.edu/data/netpolicy.html.",
abstract = "An illustration of how we might use EML metadata to describe an ecological forecast",
dataTable = dataTable,
keywordSet = keywordSet,
coverage = coverage
)
The EFI standard is using EML’s additionalMetadata
capacity. Section 2.1 of the EFI standard describes both the basic
elements (2.1.1) and the info about model structure and uncertainty
(2.1.2).
additionalMetadata <- eml$additionalMetadata(
metadata = list(
forecast = list(
## Basic elements
timestep = "1 day", ## should be udunits parsable; already in coverage -> temporalCoverage?
forecast_horizon = "30 days",
forecast_start_time = forecast_start_time,
forecast_issue_time = Sys.time(),
forecast_iteration_id = forecast_iteration_id,
forecast_project_id = forecast_project_id,
metadata_standard_version = "0.3",
model_description = list(
forecast_model_id = forecast_model_id,
name = "discrete Lotka–Volterra model",
type = "process-based",
repository = "https://github.com/eco4cast/EFIstandards/blob/master/vignettes/logistic-metadata-example.Rmd"
),
## MODEL STRUCTURE & UNCERTAINTY CLASSES
initial_conditions = list(
# Possible values: absent, present, data_driven, propagates, assimilates
status = "present",
# Number of parameters / dimensionality
complexity = 2 ## [species 1, species 2] per depth
),
drivers = list(
status = "absent"
),
parameters = list(
status = "present",
complexity = 6 ## [r, K, alpha] x 2 spp
),
random_effects = list(
status = "absent"
),
process_error = list(
status = "propagates",
propagation = list(
type = "ensemble", # ensemble vs analytic
size = 10 # required if ensemble
),
complexity = 2,
covariance = FALSE
),
obs_error = list(
status = "present",
complexity = 2,
covariance = FALSE
)
) # forecast
) # metadata
) # eml$additionalMetadata
Within the additionalMetadata
, we anticipate the model
structure info will be the most challenging to document. All six model
structural elements / uncertainty classes need to be documented, even if
just to record that a specific element is absent in the model. The six
classes are:
| Class | Description |
|---|---|
| initial_conditions | Uncertainty in the initialization of state variables (Y) |
| drivers | Uncertainty in model drivers, covariates, and exogenous scenarios (X) |
| parameters | Uncertainty in model parameters (\(\theta\)) |
| random_effects | Unexplained variability and heterogeneity in model parameters (\(\alpha\)) |
| obs_error | Uncertainty in the observations of the output variables (g) |
| process_error | Dynamic uncertainty in the process model (\(\epsilon\)) |
Each class has a very similar structure and the only required element
in each is status
which can take on the following valid
values
| status | Description |
|---|---|
| absent | This model does not contain this concept (e.g. a linear regression model doesn’t have initial conditions, random effects, or process_error). |
| present | The model contains this concept (e.g. the model has parameters), but the values used are not derived from data and no uncertainty is represented |
| data_driven | The model contains this concept and the inputs are data driven but uncertainty in this input is not explicitly propagated into predictions. |
| propagates | The model propagates uncertainty about this term into forecasts |
| assimilates | The model iteratively updates this term through data assimilation. |
Except for ‘absent’ this list is ordinal (e.g. data_driven implies present)
Next, the <complexity>
tag is recommended, but not
required, and should list the size/dimension of each status/uncertainty
class at a single location (per dimensions defined above). For example,
the logistic model has two initial conditions (n[1], n[2]), six
parameters (r, K, and alpha for each species), and both process and
observation error on the two state variables. absent
statuses don’t need to be documented as 0 as this is implied.
The <covariance>
tag states whether the
errors/uncertainties within an uncertainty class are being treated as
independent or not.
Finally, the <propagation>
and
<assimilation>
tags provide additional information
about the methods used (see EFI standard doc).
All we need now is to combine the dataset metadata with the forecast additionalMetadata
Once we have finished building our EML metadata, we can confirm it is
valid.
This will catch any missing elements. (Recall that what is ‘required’
depends on what you include – for example, you don’t have to document a
dataTable
at all, but if you do, you have to document the
“physical” file format it is in
(e.g. csv
) and the attributes and units it uses!)
## check base EML
eml_validate(my_eml)
## [1] TRUE
## attr(,"errors")
## character(0)
## check that the EML is also a valid EFI forecast
EFIstandards::forecast_validator(my_eml)
## • Checking Validity of EML file...
## ✔ EML is valid
## ✔ additionalMetadata found
## ✔ timestep parsable
## ✔ forecast_horizon parsable
## ✔ forecast_issue_time found
## ✔ forecast_iteration_id found
## ✔ forecast_project_id found
## ✔ metadata_standard_version found
## ✔ model_description found
## ✔ forecast_model_id found
## ✔ name found
## ✔ type found
## ✔ repository found
## ✔ initial_conditions found
## ✔ status found
## ✔ initial_conditions status/uncertainty class valid: present
## ✔ complexity valid
## ✔ parameters found
## ✔ status found
## ✔ parameters status/uncertainty class valid: present
## ✔ complexity valid
## ✔ drivers found
## ✔ status found
## ✔ drivers status/uncertainty class valid: absent
## ✔ random_effects found
## ✔ status found
## ✔ random_effects status/uncertainty class valid: absent
## ✔ process_error found
## ✔ status found
## ✔ process_error status/uncertainty class valid: propagates
## ✔ complexity valid
## ✔ type found
## ✔ process_error propagation type valid: ensemble
## ✔ size valid
## ✔ obs_error found
## ✔ status found
## ✔ obs_error status/uncertainty class valid: present
## ✔ complexity valid
## [1] TRUE
## attr(,"errors")
## character(0)
We are now ready to write out a valid EML document:
At this point, we could easily upload this metadata along with the data itself to a repository (e.g. DataONE) manually or via an API.
We can also generate a JSON-LD version of EML:


After I became an IEEE Certified Software Development Professional, many of my friends asked me about it and how to prepare for it. As a CSDP holder, let me introduce CSDP for you and how I prepared for it.
The CSDP credential is intended for mid-career software development professionals that want to confirm their proficiency of standard software development practices and advance in their careers.
Who is eligible to take the CSDP?
Licensed SW Engineers and IEEE Senior Members are already qualified for the CSDP. All others must meet the following:
Education: (need at least one)
Experience: (need at least one)
Preparing for CSDP
Unfortunately, IEEE Computer Society didn’t provide or recommend a specific training material for CSDP. All what they provided is:
Of course preparation depends on your knowledge level and experience you have. Below the materials that I used:
Guide to the Software Engineering Body of Knowledge | CS Press
Software Engineering, 8th Edition | Ian Sommerville | Addison Wesley
Code Complete, 2nd Edition | Steve McConnell | Microsoft Press
Software Engineering | IIT Bombay NPTEL Online Course , Prof. Rushikesh K Joshi
Software Engineering | UC Berkeley Online Course, Fall 2010 , Prof. Armando Fox
Principles of Software Engineering | University of Washington Online Course, Autumn 2007 , Prof. David Notkin
For software process only, the podcast series “IEEE Talks Software Process”
For software architecture, the podcast series “IEEE Software on architecture with Grady Booch”
Although these resources looks comprehensive, questions in the exam may not be completely covered by these resource. So, try to enrich your knowledge and experience in software engineering as much as you can and Good Luck.


Reset form
Build your first sandwich
Type of bread
Brown
Wheat
White
Toppings
Cheese
Peanutbutter
Salami
Build your second sandwich
Type of bread
Brown
Wheat
White
Toppings
Cheese
Peanutbutter
Salami


SHOP
LANE
Clothing
Accessories
FitBit-19 The Smartest Watch
Lorem ipsum dolor sit amet consectetur adipisicing elit. Officiis,
Select Color
Buy Now


Aggregate of 75.34% with good understanding of Software Development
Aggregate of 49.79%, Subject: Maths, Physics, Chemistry, Biology, English
Aggregate of 72.53%
Project Completed In Karachi
This is an eCommerce website to sell fresh vegetables and fruits online.
Customers can visit the website and order fresh vegetables without going outside.
The vendor will deliver the ordered items to the customer doorstep.
We aim to promote healthy eating by providing easy access to the best and freshest produce.
By supporting local farms and promoting domestic agriculture, we play an active role in the community
Visit Project
Project Completed In Netherlands
This website design for Dutch Caribbean people can see the flight status.
Also, there is some section for who wants to join as a pilot. there are training, event, exam,
vacancies, departments many more facilities available.
We welcome members with all levels of experience in aviation, from the seasoned pilot/controller
to the desktop enthusiast.
We provide comprehensive training to members on request.
Visit Project


Climbing a mountain on a bike with Bagger & Chispas: The Boundary Trail near Taos New Mexico
Hiking around Mayan Ruins near Talum Mexico with Missy Momma
The Mo Bro's: Jeremy, Spencer & Ben
House Concerts: Amazing Acoustic Music by Kim Warner & Carl Minor


If you walk through Berkeley, you will probably see more people in hoodies and sweatpants rather than jackets and ties. So, as a menswear enthusiast based in the Bay Area, I frequently get questions about what got me into suits and ties. So, I figured I’d write about this here.
Growing up, I spent a lot of time with my grandpa. As a former high school principal, Grandpa was accustomed to projecting authority through his clothes, and a wardrobe to match. Specifically, I remember he had four separate suits. The first, bought for cheap, was the suit he wore for going shopping to the open-air farmer’s market. The second, slightly more upscale, was for going to supermarkets (i.e. the indoor ones) and picking me up from school. A third suit would be for “general use,” such as photos, greeting guests, and attending social functions. The last suit was reserved for “special occasions only.” A 60th birthday gift from his children, the suit was from China’s then-top-designer and had a sticker price worth a few months of an average man’s salary. When I asked Grandpa to show it to me the last time I was back in Beijing, he informed me that the suit was safely locked away in a suitcase, and will only be brought out “when the occasion is right.”
However, I liked sweats and hated shopping as much as any other kid. It was an eye surgery during high school that finally exposed me to the more “respectable” parts of the menswear spectrum. After the procedure, doctors warned me to avoid pulling garments over the eye. This meant for a month post-surgery, I could only wear button-ups – I was forced to explore what I could do with them, and the habit eventually became stuck. I found that I was beginning to wear collared shirts by choice, rather than simply to protect my eye.
To make things arguably worse, I soon discovered the world of “thrifty menswear,” a community of men who seek treat purchasing menswear with the same attitude some have towards cars – “let someone else absorb the cost of buying new!” After all, quality, well-maintained suits or ties should last for decades. Furthermore, frequent sales and deals could bring the cost of new garments close to that of a “club fundraiser” t-shirt. As a result, my wardrobe grew, and we all know what happened next. Today, I own over 50 ties, write my own fashion blog, and teach workshops telling engineers how to dress for an interview.
Interesting how things go, isn’t it?


project days
This is a website for a towing and recovery business. I used a template for the mechanisims. I did all the design.
You can see this at
This is a website for a for a restraunt. I used a template for the mechanisims. I did all the design.
You can see this at
This is a video of a website I designed for My Final Project At CSU Global for
the Web Design and Development class


--- start: 2016-03-02 17:00 edition: 3 talk: "speaker.html" about: "
In today’s world, Internet of Things enable man and machine to collaborate and ideate towards unparalleled intelligence.
How would you plan for the union of solution and hardware? This is our focus point at this edition of Converge, Chennai.
Register now, to know everything there is for hardware integration in IoT.
Meet with colleagues from the industry, gain insights and have loads of fun! For more, write to<EMAIL_ADDRESS>" agenda: - time: "5:00 PM" title: "Registration" - time: "5:10 PM" title: "Welcome Note" subtitle: "" - time: "5:20 PM" title: "A project in Industrial IoT - Vidhya Sriram" subtitle: "Providing connected solutions for industrial applications" - time: "6:00 PM" title: "How it all comes together - Abhinav M" subtitle: "When everything will become connected, there are some devices that will become the interface between us the humans, and our connected devices" - time: "6:40 PM" title: "To Trim The Feet Or Trim The Shoes? - Mani HK , Mayukhini Pande" subtitle: "How to build lean IoT products without hurting the user's feet, when time and money are your scarce resource" - time: "7:20 PM" title: "Thank you Note & Felicitations" - time: "7:40 PM" title: "Networking Dinner" speaker: left: - name: "Vidhya Sriram" link: "https://www.linkedin.com/in/vidhya-sriram-17493454" designation: "Director, PS Power Controls, PSPC Exports (P) Ltd." description: "Experienced Professional, with 17 years experience in Management - Manufacturing" speaker_image: vidhya_sriram.jpg - name: "Abhinav M" link: "https://in.linkedin.com/in/abhinav-manchanda-5064489" designation: "Application Developer, ThoughtWorks" description: "Abhinav serves ThoughtWorks in the capacity of a Lead Consultant with over nine years of experience in the creation of complex applications. His main area of focus recently has been Mobile Applications, with an expertise in Android" speaker_image: abhinav_m.jpg right: - name: "Mani HK" link: "https://www.linkedin.com/in/manihk" designation: "Greenopia" description: "Serial Entrepreneur who started his first company at age 13" speaker_image: manihk.jpg - name: "Mayukhini Pande" link: "https://www.linkedin.com/in/mayukhinipande" designation: "Greenopia" description: "Experienced in both qualitative, field-based research methods such as Ethnography as well as quantitative, lab-based research methods and their application to design problems" speaker_image: mayukhini_pande.jpg ---


Puppet Class: aem_stack_manager::application_properties
- Defined in:
- manifests/application_properties.pp
Summary
Write the `application.properties` file.Overview
This class writes the application.properties
file for the AEM
Stack Manager. It is auto-generated and should not be modified by hand.
Documentation for each of the properties can be found in the example
application.properties
from which it is generated. (see below)
Note: This is an internal class that shouldn't be used
directly. It is included by the aem_stack_manager
class. You
can change values for it's parameters using Hiera.
Copyright © 2017 Shine Solutions Group, unless otherwise noted.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'manifests/application_properties.pp', line 135
class aem_stack_manager::application_properties (
String $path,
String $owner,
String $group,
String $mode,
Variant[String, Undef] $aem_stop_sleep_seconds = undef,
Variant[String, Undef] $aws_client_connection_timeout = undef,
Variant[String, Undef] $aws_client_max_error_retry = undef,
Variant[String, Undef] $aws_client_protocol = undef,
Variant[String, Undef] $aws_client_proxy_host = undef,
Variant[String, Undef] $aws_client_proxy_port = undef,
Variant[String, Undef] $aws_client_use_proxy = undef,
Variant[String, Undef] $aws_region = undef,
Variant[String, Undef] $aws_sqs_queue_name = undef,
Variant[String, Undef] $command_check_crx_quickstart_process = undef,
Variant[String, Undef] $command_check_oak_run_process = undef,
Variant[String, Undef] $command_check_snapshot_process = undef,
Variant[String, Undef] $command_deploy_artifact = undef,
Variant[String, Undef] $command_deploy_artifacts = undef,
Variant[String, Undef] $command_ec2_metadata = undef,
Variant[String, Undef] $command_enter_standby_by_component = undef,
Variant[String, Undef] $command_enter_standby_by_identity = undef,
Variant[String, Undef] $command_exit_standby_by_component = undef,
Variant[String, Undef] $command_exit_standby_by_identity = undef,
Variant[String, Undef] $command_export_package = undef,
Variant[String, Undef] $command_import_package = undef,
Variant[String, Undef] $command_offline_compaction_by_identity = undef,
Variant[String, Undef] $command_offline_compaction_for_author = undef,
Variant[String, Undef] $command_offline_snapshot = undef,
Variant[String, Undef] $command_paired_instance = undef,
Variant[String, Undef] $command_promote_author = undef,
Variant[String, Undef] $command_shell = undef,
Variant[String, Undef] $command_stack_components = undef,
Variant[String, Undef] $command_start_aem = undef,
Variant[String, Undef] $command_stop_aem = undef,
Variant[String, Undef] $command_timeout = undef,
Variant[String, Undef] $command_wait_until_ready = undef,
Variant[String, Undef] $offline_snapshot_minimum_publish_instances = undef,
Variant[String, Undef] $server_port = undef,
) {
file { $path:
ensure => file,
owner => $owner,
group => $group,
mode => $mode,
content => template('aem_stack_manager/application_properties.erb'),
}
}
|


Citations are retrieved from articles in CrossRef. This isn't a definitive list.
#} {##} {#Showing dataset views per {{ g.date_interval }}.
{% else %}Sorry, we do not have any view statistics for this dataset yet.
{% endif %}Showing total downloads for this dataset resources
| Resource | Total downloads |
|---|---|
| {% link_for resource['name'], 'resource.read', id=g.pkg.name, resource_id=resource['id'] %} | {{ resource['total'] }} |
| Total | {{ g.total_downloads }} |
Sorry, we do not have any download statistics for this dataset yet.
{% endif %}


Mouse over to interact
Built by
Dennis Jin
/
dennisjin.com
/
Open-sourced on Github
/
View more eexperiments