Who is This Guide For?
This guide is written for user who have never used, have had limited exposure to, or only accomplished specific tasks within NiFi. This guide is not intended to be an exhaustive instruction manual or a reference guide. The User Guide provides a great deal of information and is intended to be a much more exhaustive resource and is very useful as a reference guide, as well. This guide, in comparison, is intended to provide users with just the information needed in order to understand how to work with NiFi in order to quickly and easily build powerful and agile dataflows.
Because some of the information in this guide is applicable only for first-time users while other information may be applicable for those who have used NiFi a bit, this guide is broken up into several different sections, some of which may not be useful for some readers. Feel free to jump to the sections that are most appropriate for you.
This guide does expect that the user has a basic understanding of what NiFi is and does not delve into this level of detail. This level of information can be found in the Overview documentation.
Terminology Used in This Guide
In order to talk about NiFi, there are a few key terms that readers should be familiar with. We will explain those NiFi-specific terms here, at a high level.
FlowFile: Each piece of "User Data" (i.e., data that the user brings into NiFi for processing and distribution) is referred to as a FlowFile. A FlowFile is made up of two parts: Attributes and Content. The Content is the User Data itself. Attributes are key-value pairs that are associated with the User Data.
Processor: The Processor is the NiFi component that is responsible for creating, sending, receiving, transforming, routing, splitting, merging, and processing FlowFiles. It is the most important building block available to NiFi users to build their dataflows.
Downloading and Installing NiFi
NiFi can be downloaded from the NiFi Downloads Page. There are two packaging options available: a "tarball" that is tailored more to Linux and a zip file that is more applicable for Windows users. Mac OSX users may also use the tarball or can install via Homebrew.
To install via Homebrew, simply run the command brew install nifi
.
For users who are not running OSX or do not have Homebrew installed, after downloading the version of NiFi that you would like to use simply extract the archive to the location that you wish to run the application from.
For information on how to configure the instance of NiFi (for instance, to configure security, data storage configuration, or the port that NiFi is running on), see the Admin Guide.
Starting NiFi
Once NiFi has been downloaded and installed as described above, it can be started by using the mechanism appropriate for your operating system.
For Windows Users
For Windows users, navigate to the folder where NiFi was installed. Within this folder is a subfolder
named bin
. Navigate to this subfolder and double-click the run-nifi.bat
file.
This will launch NiFi and leave it running in the foreground. To shut down NiFi, select the window that was launched and hold the Ctrl key while pressing C.
For Linux/Mac OSX users
For Linux and OSX users, use a Terminal window to navigate to the directory where NiFi was installed.
To run NiFi in the foreground, run bin/nifi.sh run
. This will leave the application running until
the user presses Ctrl-C. At that time, it will initiate shutdown of the application.
To run NiFi in the background, instead run bin/nifi.sh start
. This will initiate the application to
begin running. To check the status and see if NiFi is currently running, execute the command bin/nifi.sh status
.
NiFi can be shutdown by executing the command bin/nifi.sh stop
.
Installing as a Service
Currently, installing NiFi as a service is supported only for Linux and Mac OSX users. To install the application
as a service, navigate to the installation directory in a Terminal window and execute the command bin/nifi.sh install
to install the service with the default name nifi
. To specify a custom name for the service, execute the command
with an optional second argument that is the name of the service. For example, to install NiFi as a service with the
name dataflow
, use the command bin/nifi.sh install dataflow
.
Once installed, the service can be started and stopped using the appropriate commands, such as sudo service nifi start
and sudo service nifi stop
. Additionally, the running status can be checked via sudo service nifi status
.
I Started NiFi. Now What?
Now that NiFi has been started, we can bring up the User Interface (UI) in order to create and monitor our dataflow.
To get started, open a web browser and navigate to http://localhost:8080/nifi
. The port can be changed by
editing the nifi.properties
file in the NiFi conf
directory, but the default port is 8080.
This will bring up the User Interface, which at this point is a blank canvas for orchestrating a dataflow:
Near the top of the UI are a few toolbars that will be very important to create your first dataflow:
Adding a Processor
We can now begin creating our dataflow by adding a Processor to our canvas. To do this, drag the Processor icon from the top-left of the screen into the middle of the canvas (the graph paper-like background) and drop it there. This will give us a dialog that allows us to choose which Processor we want to add:
We have quite a few options to choose from. For the sake of becoming oriented with the system, let’s say that we
just want to bring in files from our local disk into NiFi. When a developer creates a Processor, the developer can
assign "tags" to that Processor. These can be thought of as keywords. We can filter by these tags or by Processor
name by typing into the Filter box in the top-right corner of the dialog. Type in the keywords that you would think
of when wanting to ingest files from a local disk. Typing in keyword "file", for instance, will provide us a few
different Processors that deal with files. Filtering by the term "local" will narrow down the list pretty quickly,
as well. If we select a Processor from the list,
we will see a brief description of the Processor near the bottom of the dialog. This should tell us exactly what
the Processor does. The description of the GetFile Processor tells us that it pulls data from our local disk
into NiFi and then removes the local file. We can then double-click the Processor type or select it and choose the
Add
button. The Processor will be added to the canvas in the location that it was dropped.
Configuring a Processor
Now that we have added the GetFile Processor, we can configure it by right-clicking on the Processor and choosing
the Configure
menu item. The provided dialog allows us to configure many different options that can be read about
in the User Guide, but for the sake of this guide, we will focus on the Properties tab. Once
the Properties tab has been selected, we are given a list of several different properties that we can configure
for the Processor. The properties that are available depend on the type of Processor and are generally different
for each type. Properties that are in bold are required properties. The Processor cannot be started until all required
properties have been configured. The most important property to configure for GetFile is the directory from which
to pick up files. If we set the directory name to ./data-in
, this will cause the Processor to start picking up
any data in the data-in
subdirectory of the NiFi Home directory. We can choose to configure several different
Properties for this Processor. If unsure what a particular Property does, we can hover over the help icon (
)
next to the Property Name with the mouse in order to read a description of the property. Additionally, the
tooltip that is displayed when hovering over the help icon will provide the default value for that property,
if one exists, information about whether or not the property supports the Expression Language (see the
Expression Language / Using Attributes in Property Values section below), and previously configured values for that property.
In order for this property to be valid, create a directory named data-in
in the NiFi home directory and then
click the OK
button to close the dialog.
Connecting Processors
Each Processor has a set of defined "Relationships" that it is able to send data to. When a Processor finishes handling
a FlowFile, it transfers it to one of these Relationships. This allows a user to configure how to handle FlowFiles based
on the result of Processing. For example, many Processor define two Relationships: success
and failure
. Users are
then able to configure data to be routed through the flow one way if the Processor is able to successfully process
the data and route the data through the flow in a completely different many if the Processor cannot process the
data for some reason. Or, depending on the use case, the may simply route both relationships to the same route through
the flow.
Now that we have added and configured our GetFile processor and applied the configuration, we can see in the
top-left corner of the Processor an Alert icon (
) signaling that the Processor is not in a valid state. Hovering over this icon, we can see that the success
relationship has not been defined. This simply means that we have not told NiFi what to do with the data that the Processor
transfers to the success
Relationship.
In order to address this, let’s add another Processor that we can connect the GetFile Processor to, by following the same steps above. This time, however, we will simply log the attributes that exist for the FlowFile. To do this, we will add a LogAttributes Processor.
We can now send the output of the GetFile Processor to the LogAttribute Processor. Hover over the GetFile Processor
with the mouse and a Connection Icon (
) will appear over the middle of the Processor. We can drag this icon from the GetFile Processor to the LogAttribute
Processor. This gives us a dialog to choose which Relationships we want to include for this connection. Because GetFile
has only a single Relationship, success
, it is automatically selected for us.
Clicking on the Settings tab provides a handful of options for configuring how this Connection should behave:
We can give the Connection a name, if we like. Otherwise, the Connection name will be based on the selected Relationships. We can also set an expiration for the data. By default, it is set to "0 sec" which indicates that the data should not expire. However, we can change the value so that when data in this Connection reaches a certain age, it will automatically be deleted (and a corresponding EXPIRE Provenance event will be created).
The backpressure thresholds allow us to specify how full the queue is allowed to become before the source Processor is no longer scheduled to run. This allows us to handle cases where one Processor is capable of producing data faster than the next Processor is capable of consuming that data. If the backpressure is configured for each Connection along the way, the Processor that is bringing data into the system will eventually experience the backpressure and stop bringing in new data so that our system has the ability to recover.
Finally, we have the Prioritizers on the right-hand side. This allows us to control how the data in this queue is ordered. We can drag Prioritizers from the "Available prioritizers" list to the "Selected prioritizers" list in order to active the prioritizer. If multiple prioritizers are activated, they will be evaluated such that the Prioritizer listed first will be evaluated first and if two FlowFiles are determined to be equal according to that Prioritizers, the second Prioritizer will be used.
For the sake of this discuss, we can simply click Add
. to add the Connection to our graph. We should now see that the Alert
icon has changed to a Stopped icon (
). The LogAttribute Processor, however, is now invalid because its success
Relationship has not been connected to
anything. Let’s address this by signaling that data that is routed to success
by LogAttribute should be "Auto Terminated,"
meaning that NiFi should consider the FlowFile’s processing complete and "drop" the data. To do this, we configure the
LogAttribute Processor. On the Settings tab, in the right-hand side we can check the box next to the success
Relationship
to Auto Terminate the data. Clicking OK
will close the dialog and show that both Processors are now stopped.
Starting and Stopping Processors
At this point, we have two Processors on our graph, but nothing is happening. In order to start the Processors, we can
click on each one individually and then right-click and choose the Start
menu item. Alternatively, we can select the first
Processor, and then hold the Shift key while selecting the other Processor in order to select both. Then, we can
right-click and choose the Start
menu item. As an alternative to using the context menu, we can select the Processors and
then click the Start icon in the toolbar at the top of the screen.
Once started, the icon in the top-left corner of the Processors will change from a stopped icon to a Running icon. We can then stop the Processors in the same manner that we started them but using the Stop icon in the toolbar or the Stop menu item as opposed to the Start button.
Once a Processor has started, we are not able to configure it anymore. Instead, when we right-click on the Processor, we are given the option to view its current configuration. In order to configure a Processor, we must first stop the Processor and wait for any tasks that may be executing to finish. The number of tasks currently executing is shown in the top-right corner of the Processor, but nothing is shown there if there are currently no tasks.
Getting More Info for a Processor
With each Processor having the ability to expose multiple different Properties and Relationships, it can become quite
difficult to remember how all of the different pieces work for each Processor. To address this, you are able to right-click
on a Processor and choose the Usage
menu item. This will provide you with the Processor’s usage information, such as a
description of the Processor, the different Relationships that are available, when the different Relationships are used,
Properties that are exposed by the Processor and their documentation, as well as which FlowFile Attributes (if any) are
expected on incoming FlowFiles and which Attributes (if any) are added to outgoing FlowFiles.
Other Components
The toolbar that provides users the ability to drag and drop Processors onto the graph includes several other components that can be used to build a dataflow. These components include Input and Output Ports, Funnels, Process Groups, and Remote Process Groups. Due to the intended scope of this document, we will not discuss these elements here, but information is readily available in the Building a Dataflow section of the User Guide.
What Processors are Available
In order to create an effective dataflow, the users must understand what types of Processors are available to them. NiFi contains many different Processors out of the box. These Processors provide capabilities to ingest data from numerous different systems, route, transform, process, split, and aggregate data, and distribute data to many systems.
The number of Processors that are available increases in nearly each release of NiFi. As a result, we will not attempt to name each of the Processors that are available, but we will highlight some of the most frequently used Processors, categorizing them by their functions.
Data Transformation
-
CompressContent: Compress or Decompress Content
-
ConvertCharacterSet: Convert the character set used to encode the content from one character set to another
-
EncryptContent: Encrypt or Decrypt Content
-
ReplaceText: Use Regular Expressions to modify textual Content
-
TransformXml: Apply an XSLT transform to XML Content
Routing and Mediation
-
ControlRate: Throttle the rate at which data can flow through one part of the flow
-
DetectDuplicate: Monitor for duplicate FlowFiles, based on some user-defined criteria. Often used in conjunction with HashContent
-
DistributeLoad: Load balance or sample data by distributing only a portion of data to each user-defined Relationship
-
MonitorActivity: Sends a notification when a user-defined period of time elapses without any data coming through a particular point in the flow. Optionally send a notification when dataflow resumes.
-
RouteOnAttribute: Route FlowFile based on the attributes that it contains.
-
ScanAttribute: Scans the user-defined set of Attributes on a FlowFile, checking to see if any of the Attributes match the terms found in a user-defined dictionary.
-
RouteOnContent: Search Content of a FlowFile to see if it matches any user-defined Regular Expression. If so, the FlowFile is routed to the configured Relationship.
-
ScanContent: Search Content of a FlowFile for terms that are present in a user-defined dictionary and route based on the presence or absence of those terms. The dictionary can consist of either textual entries or binary entries.
-
ValidateXml: Validation XML Content against an XML Schema; routes FlowFile based on whether or not the Content of the FlowFile is valid according to the user-defined XML Schema.
Database Access
-
ConvertJSONToSQL: Convert a JSON document into a SQL INSERT or UPDATE command that can then be passed to the PutSQL Processor
-
ExecuteSQL: Executes a user-defined SQL SELECT command, writing the results to a FlowFile in Avro format
-
PutSQL: Updates a database by executing the SQL DDM statement defined by the FlowFile’s content
Attribute Extraction
-
EvaluateJsonPath: User supplies JSONPath Expressions (Similar to XPath, which is used for XML parsing/extraction), and these Expressions are then evaluated against the JSON Content to either replace the FlowFile Content or extract the value into the user-named Attribute.
-
EvaluateXPath: User supplies XPath Expressions, and these Expressions are then evaluated against the XML Content to either replace the FlowFile Content or extract the value into the user-named Attribute.
-
EvaluateXQuery: User supplies an XQuery query, and this query is then evaluated against the XML Content to either replace the FlowFile Content or extract the value into the user-named Attribute.
-
ExtractText: User supplies one or more Regular Expressions that are then evaluated against the textual content of the FlowFile, and the values that are extracted are then added as user-named Attributes.
-
HashAttribute: Performs a hashing function against the concatenation of a user-defined list of existing Attributes.
-
HashContent: Performs a hashing function against the content of a FlowFile and adds the hash value as an Attribute.
-
IdentifyMimeType: Evaluates the content of a FlowFile in order to determine what type of file the FlowFile encapsulates. This Processor is capable of detecting many different MIME Types, such as images, word processor documents, text, and compression formats just to name a few.
-
UpdateAttribute: Adds or updates any number of user-defined Attributes to a FlowFile. This is useful for adding statically configured values, as well as deriving Attribute values dynamically by using the Expression Language. This processor also provides an "Advanced User Interface," allowing users to update Attributes conditionally, based on user-supplied rules.
System Interaction
-
ExecuteProcess: Runs the user-defined Operating System command. The Process’s StdOut is redirected such that the content that is written to StdOut becomes the content of the outbound FlowFile. This Processor is a Source Processor - its output is expected to generate a new FlowFile, and the system call is expected to receive no input. In order to provide input to the process, use the ExecuteStreamCommand Processor.
-
ExecuteStreamCommand: Runs the user-defined Operating System command. The contents of the FlowFile are optionally streamed to the StdIn of the process. The content that is written to StdOut becomes the content of hte outbound FlowFile. This Processor cannot be used a Source Processor - it must be fed incoming FlowFiles in order to perform its work. To perform the same type of functionality with a Source Processor, see the ExecuteProcess Processor.
Data Ingestion
-
GetFile: Streams the contents of a file from a local disk (or network-attached disk) into NiFi and then deletes the original file. This Processor is expected to move the file from one location to another location and is not to be used for copying the data.
-
GetFTP: Downloads the contents of a remote file via FTP into NiFi and then deletes the original file. This Processor is expected to move the data from one location to another location and is not to be used for copying the data.
-
GetSFTP: Downloads the contents of a remote file via SFTP into NiFi and then deletes the original file. This Processor is expected to move the data from one location to another location and is not to be used for copying the data.
-
GetJMSQueue: Downloads a message from a JMS Queue and creates a FlowFile based on the contents of the JMS message. The JMS Properties are optionally copied over as Attributes, as well.
-
GetJMSTopic: Downloads a message from a JMS Topic and creates a FlowFile based on the contents of the JMS message. The JMS Properties are optionally copied over as Attributes, as well. This Processor supports both durable and non-durable subscriptions.
-
GetHTTP: Downloads the contents of a remote HTTP- or HTTPS-based URL into NiFi. The Processor will remember the ETag and Last-Modified Date in order to ensure that the data is not continually ingested.
-
ListenHTTP: Starts an HTTP (or HTTPS) Server and listens for incoming connections. For any incoming POST request, the contents of the request are written out as a FlowFile, and a 200 response is returned.
-
ListenUDP: Listens for incoming UDP packets and creates a FlowFile per packet or per bundle of packets (depending on configuration) and emits the FlowFile to the success relationship.
-
GetHDFS: Monitors a user-specified directory in HDFS. Whenever a new file enters HDFS, it is copied into NiFi and deleted from HDFS. This Processor is expected to move the file from one location to another location and is not to be used for copying the data. This Processor is also expected to be run On Primary Node only, if run within a cluster. In order to copy the data from HDFS and leave it in-tact, or to stream the data from multiple nodes in the cluster, see the ListHDFS Processor.
-
ListHDFS / FetchHDFS: ListHDFS monitors a user-specified directory in HDFS and emits a FlowFile containing the filename for each file that it encounters. It then persists this state across the entire NiFi cluster by way of a Distributed Cache. These FlowFiles can then be fanned out across the cluster and sent to the FetchHDFS Processor, which is responsible for fetching the actual content of those files and emitting FlowFiles that contain the content fetched from HDFS.
-
FetchS3Object: Fetches the contents of an object from the Amazon Web Services (AWS) Simple Storage Service (S3). The outbound FlowFile contains the contents received from S3.
-
GetKafka: Consumes messages from Apache Kafka. The messages can be emitted as a FlowFile per message or can be batched together using a user-specified delimiter.
-
GetMongo: Executes a user-specified query against MongoDB and writes the contents to a new FlowFile.
-
GetTwitter: Allows Users to register a filter to listen to the Twitter "garden hose" or Enterprise endpoint, creating a FlowFile for each tweet that is received.
Data Egress / Sending Data
-
PutEmail: Sends an E-mail to the configured recipients. The content of the FlowFile is optionally sent as an attachment.
-
PutFile: Writes the contents of a FlowFile to a directory on the local (or network attached) file system.
-
PutFTP: Copies the contents of a FlowFile to a remote FTP Server.
-
PutSFTP: Copies the contents of a FlowFile to a remote SFTP Server.
-
PutJMS: Sends the contents of a FlowFile as a JMS message to a JMS broker, optionally adding JMS Properties based on Attributes.
-
PutSQL: Executes the contents of a FlowFile as a SQL DDL Statement (INSERT, UPDATE, or DELETE). The contents of the FlowFile must be a valid SQL statement. Attributes can be used as parameters so that the contents of the FlowFile can be parameterized SQL statements in order to avoid SQL injection attacks.
-
PutKafka: Sends the contents of a FlowFile to Kafka as a message. The FlowFile can be sent as a single message or a delimiter, such as a new-line can be specified, in order to send many messages for a single FlowFile.
-
PutMongo: Sends the contents of a FlowFile to Mongo as an INSERT or an UPDATE.
Splitting and Aggregation
-
SplitText: SplitText takes in a single FlowFile whose contents are textual and splits it into 1 or more FlowFiles based on the configured number of lines. For example, the Processor can be configured to split a FlowFile into many FlowFiles, each of which is only 1 line.
-
SplitJson: Allows the user to split a JSON object that is comprised of an array or many child objects into a FlowFile per JSON element.
-
SplitXml: Allows the user to split an XML message into many FlowFiles, each containing a segment of the original. This is generally used when several XML elements have been joined together with a "wrapper" element. This Processor then allows those elements to be split out into individual XML elements.
-
UnpackContent: Unpacks different types of archive formats, such as ZIP and TAR. Each file within the archive is then transferred as a single FlowFile.
-
MergeContent: This Processor is responsible for merging many FlowFiles into a single FlowFile. The FlowFiles can be merged by concatenating their content together along with optional header, footer, and demarcator, or by specifying an archive format, such as ZIP or TAR. FlowFiles can be binned together based on a common attribute, or can be "defragmented" if they were split apart by some other Splitting process. The minimum and maximum size of each bin is user-specified, based on number of elements or total size of FlowFiles' contents, and an optional Timeout can be assigned as well so that FlowFiles will only wait for their bin to become full for a certain amount of time.
-
SegmentContent: Segments a FlowFile into potentially many smaller FlowFiles based on some configured data size. The splitting is not performed against any sort of demarcator but rather just based on byte offsets. This is used before transmitting FlowFiles in order to provide lower latency by sending many different pieces in parallel. On the other side, these FlowFiles can then be reassembled by the MergeContent processor using the Defragment mode.
-
SplitContent: Splits a single FlowFile into potentially many FlowFiles, similarly to SegmentContent. However, with SplitContent, the splitting is not performed on arbitrary byte boundaries but rather a byte sequence is specified on which to split the content.
HTTP
-
GetHTTP: Downloads the contents of a remote HTTP- or HTTPS-based URL into NiFi. The Processor will remember the ETag and Last-Modified Date in order to ensure that the data is not continually ingested.
-
ListenHTTP: Starts an HTTP (or HTTPS) Server and listens for incoming connections. For any incoming POST request, the contents of the request are written out as a FlowFile, and a 200 response is returned.
-
InvokeHTTP: Performs an HTTP Request that is configured by the user. This Processor is much more versatile than the GetHTTP and PostHTTP but requires a bit more configuration. This Processor cannot be used as a Source Processor and is required to have incoming FlowFiles in order to be triggered to perform its task.
-
PostHTTP: Performs an HTTP POST request, sending the contents of the FlowFile as the body of the message. This is often used in conjunction with ListenHTTP in order to transfer data between two different instances of NiFi in cases where Site-to-Site cannot be used (for instance, when the nodes cannot access each other directly and are able to communicate through an HTTP proxy).
-
HandleHttpRequest / HandleHttpResponse: The HandleHttpRequest Processor is a Source Processor that starts an embedded HTTP(S) server similarly to ListenHTTP. However, it does not send a response to the client. Instead, the FlowFile is sent out with the body of the HTTP request as its contents and attributes for all of the typical Servlet parameters, headers, etc. as Attributes. The HandleHttpResponse then is able to send a response back to the client after the FlowFile has finished being processed. These Processors are always expected to be used in conjunction with one another and allow the user to visually create a Web Service within NiFi. This is particularly useful for adding a front-end to a non-web- based protocol or to add a simple web service around some functionality that is already performed by NiFi, such as data format conversion.
Amazon Web Services
-
FetchS3Object: Fetches the content of an object stored in Amazon Simple Storage Service (S3). The content that is retrieved from S3 is then written to the content of the FlowFile.
-
PutS3Object: Writes the contents of a FlowFile to an Amazon S3 object using the configured credentials, key, and bucket name.
-
PutSNS: Sends the contents of a FlowFile as a notification to the Amazon Simple Notification Service (SNS).
-
GetSQS: Pulls a message from the Amazon Simple Queuing Service (SQS) and writes the contents of the message to the content of the FlowFile.
-
PutSQS: Sends the contents of a FlowFile as a message to the Amazon Simple Queuing Service (SQS).
-
DeleteSQS: Deletes a message from the Amazon Simple Queuing Service (SQS). This can be used in conjunction with the GetSQS in order to receive a message from SQS, perform some processing on it, and then delete the object from the queue only after it has successfully completed processing.
Working With Attributes
Each FlowFile is created with several Attributes, and these Attributes will change over the life of the FlowFile. The concept of a FlowFile is extremely powerful and provides three primary benefits. First, it allows the user to make routing decisions in the flow so that FlowFiles that meeting some criteria can be handled differently than other FlowFiles. This is done using the RouteOnAttribute and similar Processors.
Secondly, Attributes are used in order to configure Processors in such a way that the configurationg of the Processor is dependent on the data itself. For instance, the PutFile Processor is able to use the Attributes in order to know where to store each FlowFile, while the directory and filename Attributes may be different for each FlowFile.
Finally, the Attributes provide extremely valuable context about the data. This is useful when reviewing the Provenance data for a FlowFile. This allows the user to search for Provenance data that match specific criteria, and it also allows the user to view this context when inspecting the details of a Provenance Event. By doing this, the user is then able to gain valuable insight as to why the data was processed one way or another, simply by glancing at this context that is carried along with the content.
Common Attributes
Each FlowFile has a minimum set of Attributes:
-
filename: A filename that can be used to store the data to a local or remote file system
-
path: The name of a directory that can be used to store the data to a local or remote file system
-
uuid: A Universally Unique Identifier that distinguishes the FlowFile from other FlowFiles in the system.
-
entryDate: The date and time at which the FlowFile entered the system (i.e., was created). The value of this attribute is a number that represents the number of milliseconds since midnight, Jan. 1, 1970 (UTC).
-
lineageStartDate: Any time that a FlowFile is cloned, merged, or split, this results in a "child" FlowFile being created. As those children are then cloned, merged, or split, a chain of ancestors is built. This value represents the date and time at which the oldest ancestor entered the system. Another way to think about this is that this attribute represents the latency of the FlowFile through the system. The value is a number that represents the number of milliseconds since midnight, Jan. 1, 1970 (UTC).
-
fileSize: This attribute represents the number of bytes taken up by the FlowFile’s Content.
Note that the uuid
, entryDate
, lineageStartDate
, and fileSize
attributes are system-generated and cannot be changed.
Extracting Attributes
NiFi provides several different Processors out of the box for extracting Attributes from FlowFiles. A list of commonly used Processors for this purpose can be found above in the Attribute Extraction section. This is a very common use case for building custom Processors, as well. Many Processors are written to understand a specific data format and extract pertinent information from a FlowFile’s content, creating Attributes to hold that information, so that decisions can then be made about how to route or process the data.
Adding User-Defined Attributes
In addition to having Processors that are able to extract particular pieces of information from FlowFile content into Attributes, it is also common for users to want to add their own user-defined Attributes to each FlowFile at a particular place in the flow. The UpdateAttribute Processor is designed specifically for this purpose. Users are able to add a new property to the Processor in the Configure dialog by clicking the "New Property" button in the top-right corner of the Properties tab. The user is then prompted to enter the name of the property and then a value. For each FlowFile that is processed by this UpdateAttribute Processor, an Attribute will be added for each user-defined property. The name of the Attribute will be the same as the name of the property that was added. The value of the Attribute will be the same as the value of the property.
The value of the property may contain the Expression Language, as well. This allows Attributes to be modified or added
based on other Attributes. For example, if we want to prepend the hostname that is processing a file as well as the date to
a filename, we could do this by adding a property with the name filename
and the value ${hostname()}-${now():format('yyyy-dd-MM')}-${filename}
.
While this may seem confusing at first, the section below on Expression Language / Using Attributes in Property Values will help to clear up what is going on
here.
In addition to always adding a defined set of Attributes, the UpdateAttribute Processor has an Advanced UI that allows the user
to configure a set of rules for which Attributes should be added when. To access this capability, in the Configure dialog’s
Properties tab, click the Advanced...
button at the bottom of the dialog. This will provide a UI that is tailored specifically
to this Processor, rather than the simple Properties table that is provided for all Processors. Within this UI, the user is able
to configure a rules engine, essentially, specifying rules that must match in order to have the configured Attributes added
to the FlowFile.
Routing on Attributes
One of the most powerful features of NiFi is the ability to route FlowFiles based on their Attributes. The primary mechanism for doing this is the RouteOnAttribute Processor. This Processor, like UpdateAttribute, is configured by adding user-defined properties. Any number of properties can be added by clicking the "New Property" icon in the top-right corner of the Properties tab in the Processor’s Configure dialog.
Each FlowFile’s Attributes will be compared against the configured properties to determine whether or not the FlowFile meets the specified criteria. The value of each property is expected to be an Expression Language expression and return a boolean value. For more on the Expression Language, see the Expression Language / Using Attributes in Property Values section below.
After evaluating the Expression Language expressions provided against the FlowFile’s Attributes, the Processor determines how to route the FlowFile based on the Routing Strategy selected. The most common strategy is the "Route to Property name" strategy. With this strategy selected, the Processor will expose a Relationship for each property configured. If the FlowFile’s Attributes satisfy the given expression, a copy of the FlowFile will be routed to the corresponding Relationship. For example, if we had a new property with the name "begins-with-r" and the value "${filename:startsWith('r')}" then any FlowFile whose filename starts with the letter r will be routed to that Relationship. All other FlowFiles will be routed to unmatched.
Expression Language / Using Attributes in Property Values
As we extract Attributes from FlowFiles' contents and add user-defined Attributes, they don’t do us much good as an operator unless we have some mechanism by which we can use them. The NiFi Expression Language allows us to access and manipulate FlowFile Attribute values as we configure our flows. Not all Processor properties allow the Expression Language to be used, but many do. In order to determine whether or not a property supports the Expression Language, a user can hover over the Help icon ( ) in the Properties tab of the Processor Configure dialog. This will provide a tooltip that shows a description of the property, the default value, if any, and whether or not the property supports the Expression Language.
For properties that do support the Expression Language, it is used by adding an expression within the opening ${
tag and the closing
}
tag. An expression can be as simple as an attribute name. For example, to reference the uuid
Attribute, we can simply use the
value ${uuid}
. If the Attribute name begins with any character other than a letter, or if it contians a character other than
a number, a letter, a period (.), or an underscore (_), the Attribute name will need to be quoted. For example, ${My Attribute Name}
will be invalid, but ${'My Attribute Name'}
will refer to the Attribute My Attribute Name
.
In addition to referencing Attribute values, we can perform a number of functions and comparisons on those Attributes. For example,
if we want to check if the filename
attribute contains the letter r without paying attention to case (upper case or lower case),
we can do this by using the expression ${filename:toLower():contains('r')}
. Note here that the functions are separated by colons.
We can chain together any number of functions to build up more complex expressions. It is also important to understand here that even
though we are calling filename:toLower()
, this does not alter the value of the filename
Attribute in anyway but rather just gives
us a new value to work with.
We can also embed one expression within another. For example, if we wanted to compare the value of the attr1
Attribute to
the value of the attr2
Attribute, we can do this with the following expression: ${attr1:equals( ${attr2} )}
.
The Expression Language contains many different functions that can be used in order to perform the tasks needed for routing and manipulating Attributes. Functions exist for parsing and manipulating strings, comparing string and numeric values, manipulating and replacing values, and comparing values. A full explanation of the different functions available is out of scope of this document, but the Expression Language Guide provides far greater detail for each of the functions.
In addition, this Expression Language guide is built in to the application so that users are able to easily see which functions are available and see their documentation while typing. When setting the value of a property that supports the Expression Language, if the cursor is within the Expression Language start and end tags, pressing Ctrl + Space on the keyword will provide a popup of all of the available functions and will provide auto-complete functionality. Clicking on or using the keyboard to navigate to one of the functions listed in the popup will cause a tooltip to show, which explains what the function does, the arguments that it expects, and the return type of the function.
Working With Templates
As we use Processors to build more and more complex dataflows in NiFi, we often will find that we string together the same sequence of Processors to perform some task. This can become tedious and inefficient. To address this, NiFi provides a concept of Templates. A template can be thought of as a reusable sub-flow. To create a template, follow these steps:
-
Select the components to include in the template. We can select multiple components by clicking on the first component and then holding the Shift key while selecting additional components (to include the Connections between those components), or by holding the Shift key while dragging a box around the desired components on the canvas.
-
Select the Create Template Icon ( ) from the middle toolbar at the top of the screen.
-
Provide a name and optionally comments about the template.
-
Click the Create button.
Once we have created a template, we can now use it as a building block in our flow, just as we would a Processor. To do this, we will click and drag the Template icon from the left-most toolbar onto our canvas. We can then choose the template that we would like to add or our canvas and click the Add button.
Finally, we have the ability to manage our templates by using the Template Management dialog. To access this dialog, click the Template icon in the top-right toolbar. From here, we can see which templates exist and filter the templates to find the templates of interest. On the right-hand side of the table is icon to Export, or Download, the template as an XML file. This can then be provided to others so that they can use your template.
To import a template into your NiFi instance, click the Browse button in the top-right corner of the dialog and navigate to the file on your computer. Then click the Import button. The template will now show up in your table, and you can drag it onto your canvas as you would any other template that you have created.
There are a few important notes to remember when working with templates: - Any properties that are identified as being Sensitive Properties (such as a password that is configured in a Processor) will not be added to the template. These sensitive properties will have to be populated each time that the template is added to the canvas. - If a component that is included in the template references a Controller Service, the Controller Service will also be added to the template. This means that each time that the template is added to the graph, it will create a copy of the Controller Service.
Monitoring NiFi
As data flows through your dataflow in NiFi, it is important to understand how well your system is performing in order to assess if you will require more resources and in order to assess the health of your current resources. NiFi provides a few mechanisms for monitoring your system.
Status Bar
Near the top of the NiFi screen is a blue bar that is referred to as the Status Bar. It contains a few important statistics about the current health of NiFi. The number of Active Threads can indicate how hard NiFi is currently working, and the Queued stat indicates how many FlowFiles are currently queued across the entire flow, as well as the total size of those FlowFiles.
If the NiFi instance is in a cluster, we will also see an indicator here telling us how many nodes are in the cluster and how many are currently connected. In this case, the number of active threads and the queue size are indicative of all the sum of all nodes that are currently connected.
Component Statistics
Each Processor, Process Group, and Remote Process Group on the canvas provides several statistics about how much data has been processed by the component. These statistics provide information about how much data has been processed in the past five minutes. This is a rolling window and allows us to see things like the number of FlowFiles that have been consumed by a Processor, as well as the number of FlowFiles that have been emitted by the Processor.
The connections between Processors also expose the number of items that are currently queued.
It may also be valuable to see historical values for these metrics and, if clustered, how the different nodes compare to one another. In order to see this information, we can right-click on a component and choose the Status menu item. This will show us a graph that spans the time since NiFi was started, or up to 24 hours, whichever is less. The amount of time that is shown here can be extended or reduced by changing the configuration in the properties file.
In the top-right corner is a drop-down that allows the user to select which metric they are viewing. The graph on the bottom allows the user to select a smaller portion of the graph to zoom in.
Bulletins
In addition to the statistics provided by each component, as a user we will want to know if any problems occur. While we could monitor the logs for anything interesting, it is much more convenient to have notifications pop up on the screen. If a Processor logs anything as a WARNING or ERROR, we will see a "Bulletin Indicator" show up in the top-left-hand corner of the Processor. This indicator looks like a sticky note and will be shown for five minutes after the event occurs. Hovering over the bulletin provides information about what happened so that the user does not have to sift through log messages to find it. If in a cluster, the bulletin will also indicate which node in the cluster emitted the bulletin. We can also change the log level at which bulletins will occur in the Settings tab of the Configure dialog for a Processor.
If the framework emits a bulletin, we will also see this bulletin indicator occur in the Status Bar at the top of the screen. The right-most icon in the NiFi Toolbar is the Bulletin Board icon. Clicking this icon will take us to the bulletin board where we can see all bulletins that occur across the NiFi instance and can filter based on the component, the message, etc.
Data Provenance
NiFi keeps a very granular level of detail about each piece of data that it ingests. As the data is processed through the system and is transformed, routed, split, aggregated, and distributed to other endpoints, this information is all stored within NiFi’s Provenance Repository. In order to search and view this information, we can click the Data Provenance icon ( ) in the top-right corner of the canvas. This will provide us a table that lists the Provenance events that we have searched for:
Initially, this table is populated with the most recent 1,000 Provenance Events that have occurred (though it may take a few
seconds for the information to be processed after the events occur). From this dialog, there is a Search button that allows the
user to search for events that happened by a particular Processor, for a particular FlowFile by filename or UUID, or several other
fields. The nifi.properties
file provides the ability to configure which of these properties are indexed, or made searchable.
Additionally, the properties file also allows you to choose specific FlowFile Attributes that will be indexed. As a result, you can
choose which Attributes will be important to your specific dataflows and make those Attributes searchable.
Event Details
Once we have performed our search, our table will be populated only with the events that match the search criteria. From here, we can choose the Info icon ( ) on the left-hand side of the table to view the details of that event:
From here, we can see exactly when that event occurred, which FlowFile the event affected, which component (Processor, etc.) performed the event, how long the event took, and the overall time that the data had been in NiFi when the event occurred (total latency).
The next tab provides a listing of all Attributes that existed on the FlowFile at the time that the event occurred:
From here, we can see all the Attributes that existed on the FlowFile when the event occurred, as well as the previous values for those Attributes. This allows us to know which Attributes changed as a result of this event and how they changed. Additionally, in the right-hand corner is a checkbox that allows the user to see only those Attributes that changed. This may not be particularly useful if the FlowFile has only a handful of Attributes, but can be very helpful when a FlowFile has hundreds of Attributes.
This is very important, because it allows the user to understand the exactly context in which the FlowFile was processed. This is very helpful to understand why the FlowFile was processed the way that it was, especially when the Processor was configured using the Expression Language.
Finally, we have the Content tab:
This tab provides us information about where in the Content Repository the FlowFile’s content was stored. If the event modified the content of the FlowFile, we will see the before and after content claims. We are then given the option to Download the content or to View the content within NiFi itself, if the data format is one that NiFi understands how to render.
Additionally, there is Replay button that allows the user to re-insert the FlowFile into the flow and re-process it from exactly the point at which the event happened. This provides a very powerful mechanism, as we are able to modify our flow in real time, re-process a FlowFile, and then view the results. If they are not as expected, we can modify the flow again, and re-process the FlowFile again. We are able to perform this iterative development of the flow until it is processing the data exactly as intended.
Lineage Graph
In addition to viewing the details of a Provenance event, we can also view the lineage of the FlowFile involved by clicking on the Lineage Icon ( ) from the table view.
This provides us with a graphical representation of exactly what happened to that piece of data as it traversed the system:
From here, we can right-click on any of the events represented and click the "View Details" menu item to see the Event Details. This graphical representation shows us exactly which events occurred to the data. There are a view "special" event types to be aware of. If we see a JOIN, FORK, or CLONE event, we can right-click and choose to Find Parents or Expand. This allows us to see the lineage of parent FlowFiles and children FlowFiles that were created as well.
The slider in the bottom-left corner allows us to see the time at which these events occurred. By sliding it left and right, we can see which events introduced latency into the system so that we have a very good understanding of where in our system we may need to provide more resources, such as the number of Concurrent Tasks for a Processor. Or it may reveal, for example, that most of the latency was introduced by a JOIN event, in which we were waiting for more FlowFiles to join together. In either case, the ability to easily see where this is occurring is a very powerful feature that will help users to understand how the enterprise is operating.
Where To Go For More Information
The NiFi community has built up a significant amount of documentation on how to use the software. The following guides are available, in addition to this Getting Started Guide:
-
Apache NiFi Overview - Provides an overview of what Apache NiFi is, what it does, and why it was created.
-
Apache NiFi User Guide - A fairly extensive guide that is often used more as a Reference Guide, as it has pretty lengthy in discussing all of the different components that comprise the application. This guide is written with the NiFi Operator as its audience. It provides information on each of the different components available in NiFi and explains how to use the different features provided by the application.
-
Administration Guide - A guide for setting up and administering Apache NiFi for production environments. This guide provides information about the different system-level settings, such as setting up clusters of NiFi and securing access to the web UI and data.
-
Express Language Guide - A far more exhaustive guide for understanding the Expression Language than is provided above. This guide is the definitive documentation for the NiFi Expression Language. It provides an introduction to the EL and an explanation of each function, its arguments, and return types as well as providing examples.
-
Developer’s Guide - While not an exhaustive guide to All Things NiFi Development, this guide does provide a comprehensive overview of the different API’s available and how they should be used. In addition, it provides Best Practices for developing NiFi components and common Processor idioms to help aid in understanding the logic behind many of the existing NiFi components.
-
Contributor’s Guide - A guide for explaining how to contribute work back to the Apache NiFi community so that others can make use of it.
Several blog postings have also been added to the Apache NiFi blog site: https://blogs.apache.org/nifi/
In addition to the blog and guides provided here, you can browse the different NiFi Mailing Lists or send an e-mail to one of the mailing lists at<EMAIL_ADDRESS>or<EMAIL_ADDRESS>Many of the members of the NiFi community are also available on Twitter and actively monitor for tweets that mention @apachenifi.


Module: AbstractController::Helpers::ClassMethods
| Relationships & Source Files | |
| Defined in: | actionpack/lib/abstract_controller/helpers.rb |
Instance Method Summary
-
#clear_helpers
Clears up all existing helpers in this class, only keeping the helper with the same name as this class.
-
#helper(*args, &block)
The
helper
class method can take a series of helper module names, a block, or both. -
#helper_method(*meths)
Declare a controller method as a helper.
-
#inherited(klass)
When a class is inherited, wrap its helper module in a new module.
-
#modules_for_helpers(args)
Returns a list of modules, normalized from the acceptable kinds of helpers with the following behavior:
Instance Method Details
#clear_helpers
Clears up all existing helpers in this class, only keeping the helper with the same name as this class.
# File 'actionpack/lib/abstract_controller/helpers.rb', line 117
def clear_helpers inherited_helper_methods = _helper_methods self._helpers = Module.new self._helper_methods = Array.new inherited_helper_methods.each { |meth| helper_method meth } default_helper_module! unless anonymous? end
#helper(*args, &block)
The helper
class method can take a series of helper module names, a block, or both.
Options
When the argument is a module it will be included directly in the template class.
helper FooHelper # => includes FooHelper
When the argument is a string or symbol, the method will provide the “_helper” suffix, require the file and include the module in the template class. The second form illustrates how to include custom helpers when working with namespaced controllers, or other cases where the file containing the helper definition is not in one of Rails' standard load paths:
helper :foo # => requires 'foo_helper' and includes FooHelper
helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper
Additionally, the helper
class method can receive and evaluate a block, making the methods defined available to the template.
# One line
helper { def hello() "Hello, world!" end }
# Multi-line
helper do
def foo( )
"#{} is the very best"
end
end
Finally, all the above styles can be mixed together, and the helper
method can be invoked with a mix of symbols
, strings
, modules
and blocks.
helper(:three, BlindHelper) { def mice() 'mice' end }
# File 'actionpack/lib/abstract_controller/helpers.rb', line 107
def helper(*args, &block) modules_for_helpers(args).each do |mod| add_template_helper(mod) end _helpers.module_eval(&block) if block_given? end
#helper_method(*meths)
Declare a controller method as a helper. For example, the following makes the current_user
controller method available to the view:
class ApplicationController < ActionController::Base
helper_method :current_user, :logged_in?
def current_user
@current_user ||= User.find_by(id: session[:user])
end
def logged_in?
current_user != nil
end
end
In a view:
<% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
Parameters
-
method[, method]
- A name or names of a method on the controller to be made available on the view.
# File 'actionpack/lib/abstract_controller/helpers.rb', line 60
def helper_method(*meths) meths.flatten! self._helper_methods += meths meths.each do |meth| _helpers.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1 def #{meth}(*args, &blk) # def current_user(*args, &blk) controller.send(%(#{meth}), *args, &blk) # controller.send(:current_user, *args, &blk) end # end ruby_eval end end
#inherited(klass)
When a class is inherited, wrap its helper module in a new module. This ensures that the parent class's module can be changed independently of the child class's.
# File 'actionpack/lib/abstract_controller/helpers.rb', line 33
def inherited(klass) helpers = _helpers klass._helpers = Module.new { include helpers } klass.class_eval { default_helper_module! } unless klass.anonymous? super end
#modules_for_helpers(args)
Returns a list of modules, normalized from the acceptable kinds of helpers with the following behavior:
- ::String or Symbol
-
:FooBar
or “FooBar” becomes “foo_bar_helper”,
and “foo_bar_helper.rb” is loaded using require_dependency.
- Module
-
No further processing
After loading the appropriate files, the corresponding modules are returned.
Parameters
-
args
- An array of helpers
Returns
-
::Array - A normalized list of modules for the list of helpers provided.
# File 'actionpack/lib/abstract_controller/helpers.rb', line 143
def modules_for_helpers(args) args.flatten.map! do |arg| case arg when String, Symbol file_name = "#{arg.to_s.underscore}_helper" begin require_dependency(file_name) rescue LoadError => e raise AbstractController::Helpers::MissingHelperError.new(e, file_name) end mod_name = file_name.camelize begin mod_name.constantize rescue LoadError # dependencies.rb gives a similar error message but its wording is # not as clear because it mentions autoloading. To the user all it # matters is that a helper module couldn't be loaded, autoloading # is an internal mechanism that should not leak. raise NameError, "Couldn't find #{mod_name}, expected it to be defined in helpers/#{file_name}.rb" end when Module arg else raise ArgumentError, "helper must be a String, Symbol, or Module" end end end


I am originally from Guatemala, where I went to high school, while also traveling extensively through the world with my parents to exotic locations. Among those locations we repeatedly traveled to Miami, so I have got to know that city pretty well. I have also extensively traveled to Germany (to practice my German). Thus, I feel comfortable pretty much anywhere in the world and think of it as my home!
For college I went to Penn State where I graduated with degrees in: Energy Business and Finance Energy Systems Option, Energy Engineering, Petroleum and Natural Gas Engineering, and Mining Engineering
After college I continued taking numerous courses with Harvard Business School, as well as with Georgetown and INCAE on Hospital and Health Administration, while also completing several computer science courses.
I did also earn a post-graduate degree from Penn State in Solar Energy, so not all my education has been alternative...
On top of those courses, I also gained certification from LEED for BD+C due to my interest in Energy and Natural Resources, and how our civilization interacts with them.
I've worked with my familiy on their retail and distribution business in Guatemala all my life, while also helping my father recently in his medical businesses. I also worked in an Oil firm in Belize with Petroleum Engineering and Financial Anlysis Projects. After working for the oil firm, I went back to work with my family and started my own section of the company in the US, Luszol LLC which has done several solar PV installations, but has pivoted to a more comprehensive outlook on energy, targeting numerous sources of generation for a smarter, more reliable, and decentralized grid!


In this lesson you will be learning about what a basic HTML Documnet looks like. You will come across terms such as the Document Declaration Tag, the Head tag, Body tag and much more in this lesson. This Video has been Created by Satanshu Mishra.
An accurate transcript will be added for this video at a later date.


{% extends "base.html" %} {% block js %} {{ block.super }} {% endblock %} {% block navbar %}
Your score is based on analyzing your tweets.
Loading Twitter Content...


Work your way down the tree to capture your degree as fast as possible
Go to degree plannerWhat days of the week can you take classes? We can help your find classes that fit your life.
Set AvailabilityPlan your trip and learn more about the bus schedules to plan out your schedule.
Plan with IndyGo


| tests.test_resource | index test_resource.py |
Test Resource Actions - please check the source code of this file to see how the resource actions can be used
The test functions are organised by resource class, i.e. VDataCenter, VSystem, VServer, VDisk etc.
| Functions | ||
|


Basics¶
Input-Output Methods¶
For taking input in python 2, we use raw_input()
.
1 2 3 4 | $ python >>>raw_input() this is taken as input 'this is taken as input' |
In python3, there is no need for we use input()
.
1 2 3 4 | $ python3 >>>input() this is taken as input 'this is taken as input' |
1 2 3 4 | >>>n=input() 3 >>>print(type(n)) <class 'str'> |
Typecast: Converting the datatype of a variable from one to another.
1 2 3 4 | >>>n=int(input()) 3 >>>print(type(n)) <class 'int'> |
-
In all the above cases, if python 2 is used then, in place of input() use raw_input().
-
For print statememt in python3, the synatx is
print("Secure")
. While in python 2, there is no need of parenthesis () but it won't show any error even if we use parenthesis (). It isprint "Secure"
orprint ("Secure" )
.
Operations¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | >>> a=5 >>> b=6 >>>a + b 11 >>>a - b -1 >>>a * b 30 >>>a / b 0.8333333333333334 >>>a // b 0 >>>a % b 5 >>>a ** b 15625 |
- // shows the quotient.
- % show the remainder.
- ** is a to the power b or a raised to b.
In python 2 when '/ ' operation is used, the integer is printed while in case python 3 it will show value after decimal place also. So to obtain the float value in python 2 you need to specify atleast one, either denominator or numerator as float.
1 2 3 4 5 | $ python >>> 3/2 1 >>>3.0/2 1.5 |
Comparision operators:¶
- a == b Equal to condition.
- a < b Less than condition.
- a > b Greater than condition.
- a <= b Less than or equal to condition.
- a >= b Greater than or equal to condition.
- a != b Not equal to condition.
Assignment Operator '='¶
a=b the value of b is assigned to a.
Binary Operations¶
To understand this, use python built in funtion bin(n)
. It will show the binary form of number n.
1 2 3 4 | >>> bin(3) '0b11' >>> bin(2) '0b10' |
a&b bitwise AND of a,b:¶
1 2 | >>> 3&2 2 |
a|b bitwise OR of a,b:¶
1 2 | >>> 3|2 3 |
a^b bitwise XOR of a,b:¶
1 2 | >>> 3^2 1 |
a<<b Left Shift¶
a<<b it will shift the bits of a in binary format to left, this shift is done b times:
1 2 3 4 | >>> 3<<2 12 >>>bin(12) 0b1100 |
a>>b Right Shift¶
a>>b it will shift the bits of a in binary format to right, this shift is done b times:
1 2 | >>> 3>>1 1 |
Python can also understand logical operations when written in english : - and - or - not - in
Conditional Statements¶
if statements¶
If condition statements are to be used when you have a set of statements which is to be executed when a particular condition is satisfied. For example if a person's age is above 18, he is eligible to vote. If not, he is not eligible to vote.
Example 1
1 2 3 4 5 6 7 | $ python3 >>>age=int(input()) 32 >>>if(age>=18): ... print(“you are eligible to vote”) ...else: ... print(“you are not eligible to vote”) |
Output
1 2 | you are eligible to vote >>> |
1 2 3 4 5 6 7 | $ python >>>age=int(raw_input()) 32 >>>if age>=18: ... print “you are eligible to vote” ...else: ... print “you are not eligible to vote” |
Output
1 2 | you are eligible to vote >>> |
If we have more than one condition to check we can use elif statements.
1 2 3 4 5 6 7 8 9 10 11 | $ python3 >>>age=int(input()) 32 >>>if(age<=12): ... print(“you are a kid”) ...elif(age>12 and age <= 19): ... print (“you are a teenager”) ...elif(age >19 and age < 30 ): ... print(“you are an adult”) ...else: print(“you are a senior citizen”) |
Output
1 2 | you are a senior citizen >>> |
1 2 3 4 5 6 7 8 9 10 11 | $ python >>>age=int(raw_input()) 32 >>>if age<=12 : ... print “you are a kid” ...elif age>12 and age <= 19 : ... print “you are a teenager” ...elif age >19 and age < 30 : ... print “you are an adult” ...else: print “you are a senior citizen” |
Press enter button twice for output.
Output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | you are a senior citizen >>> ``` ## Loops ### For loop It is used when you need to execute a set of statements n times. Syntax : ```sh for variable in range(start,end,incrementation): statments |
If not mentioned then starting is taken as 0 and incrementation as 1 to the specified end point.
This code is valid for both python 3 and python 2.
Example 1
1 2 3 | $ python >>>for i in range(3): ... print(“welcome to the world of security”) |
Press enter button twice for output. Output
1 2 3 4 | welcome to the world of security welcome to the world of security welcome to the world of security >>> |
This code is valid for both python 3 and python 2.
1 2 3 4 | $ python3 >>>i = "teambi0s" >>>for i in c: ... print(i) |
1 2 3 4 5 6 7 8 9 | t
e
a
m
b
i
0
s
>>>
|
While loop¶
It is used to execute a set of statements until the condition is satisfied and hence the loop will end as the condition becomes false.
Syntax :
1 2 | while(condition): statments |
This code is valid for both python 3 and python 2.
1 2 3 4 5 | $ python3 >>>flag=0 >>>while(flag!=3): ... print(flag) ... flag=flag+1 |
Output
1 2 3 4 | 0 1 2 >>> |
Nested Loops:¶
Loop inside a loop is termed as nested.
This code is valid for both python 3 and python 2.
1 2 3 4 | $ python3 >>>for i in range (3): ... for j in range (2): ... print(“this is nested”) |
Output
1 2 3 4 5 6 7 | this is nested this is nested this is nested this is nested this is nested this is nested >>> |
It will print 6 times.


{% extends "app/app_form.html" %} {% block form_info %}
Please specify your email address to receive instructions for resetting it.


--- layout: data_model title: CVEVulnerabilityType this_version: 4.1 ---
The CVEVulnerabilityType provides a way of referencing specific vulnerabilities that malware exploits or attempts to exploit via a Common Vulnerabilities and Exposures (CVE) identifier. For more information on CVE please see http://cve.mitre.org.
| Field Name | Type | Description |
|---|---|---|
| @cve_idrequired | string |
The cve_id attribute contains the ID of the CVE that is being referenced, e.g., CVE-1999-0002. |
| Description0..1 | string |
The Description field specifies the textual description of the vulnerability referenced by the cve_id. |


0.3.2
Component
is a class that should be extended for every component that's being made. It
is a helper class to keep the code uniform.
This is not to be used directly, only extended
see props on how to pass in additional configuration to the constructor.
import { Component } from '@verndale/core';
class Foo extends Component {
construction(el){
super(el);
}
setupDefaults(){
// ...defaults go here
}
addListeners(){
// ...listeners go here
}
}
// Create a new Foo component
new Foo('.foo');
Main class element, this will be a jQuery instance
This can be reachable at any time in your subclass with this.$el
after super()
is called
Type: Object
Main class element, this will be a native Node instance
This can be reachable at any time in your subclass with this.el
after super()
is called
Type: Object
This method is used for override; It's called directly after the element and configuration have been set up
This method is used for override;
It's called directly after setupDefaults()
, so everything is ready and setup at this point.
Get component configuration.
Type: Object
class Foo extends Component {
construction(el, props){
super(el, props);
}
setupDefaults(){
console.log(this.props.name); // Outputs "Foo"
}
}
// Create a new Foo component with some configuration
new Foo('.foo', {
name: 'Foo'
});
Set DOM object.
Type: Object
(any)
class Foo extends Component {
construction(el){
super(el);
}
setupDefaults(){
this.dom = {
$container: document.querySelector('.container')
}
}
addListeners(){
//DOM object is available
console.log(this.dom.$container);
}
}
// Create a new Foo component
new Foo('.foo');
Creates bundles from modules that are defined in this method. This is to be used for the main entry points for your module initialization.
create()
allows you to import any module(s) at runtime as long as the DOM element is on the page.
This method should be used to load JavaScript chunks at runtime that you don not want in the main or common bundle
and is used with the Component and render method to loop through each matched element on the page.
You must have a data-module
attribute that is the same name as the JavaScript file in the HTML
in order for create()
to detect the component.
The JavaScript file you are importing does not have to be a class
; it could be anything - ie. a single function,
an object, or a collection of utility functions.
This method will automatically look in the src
folder - this cannot be changed because we are
using dynamic imports and it needs a reliable, hardcoded folder to look in order to chunk files properly.
| Name | Description |
|---|---|
organisms[].name String
|
The path/name of the JavaScript file. |
organisms[].render Function
|
Function used to intercept the rendering of the module. |
(String)
Path to the JavaScript files you wish to dynamically bundle.
void
//'Foo' is the name of the JavaScript file

//'Bar' is the name of the JavaScript file

//create simple modules
//-- src/js/main.js
import create from '@verndale/core';
const organisms = [
{ name: 'Foo' },
{ name: 'global/Bar' }
];
create(organisms, 'js/modules');
//This will fetch the modules: `./js/modules/Foo.js` and `./js/modules/global/Bar.js`
//define some properties to the module "Bar"
//-- src/js/main.js
import create from '@verndale/core';
const organisms = [
{ name: 'Foo' },
{ name: 'global/Bar',
props: {
firstName: 'foo',
lastName: 'bar'
}
}
];
create(organisms, 'js/modules');
//intercept the render method in case we want to bring
//in other libraries or do anything else prior to render/instantiation.
//-- src/js/main.js
import create from '@verndale/core';
//in this case, `Foo.js` is a react component
const organisms = [
{ name: 'Foo',
render(Component, el){
const React = require('react');
const { render } = require('react-dom');
render(<Component {...el[0].dataset} />, el[0]);
}
}
];
create(organisms, 'js/modules');
Iterates through any matched element and provides a callback to return the DOM object.
(Object)
The DOM object to be used to iterate through.
(Function)
Callback which returns the raw element.
void
import { render } from '@verndale/core';
render(document.querySelectorAll('.foo'), $target => {
new Foo($target);
});


DecadeStyles
Overview
For this task, I wanted to build a clothing style classifier by decade. I could not find an existing dataset labeling attire style by decade, so I built one manually from Google images. Once this process was complete, I used transfer learning on a pre-trained deep-learning model to build my classifier.
Link to application:DecadeStyles
Data Collection
The magician’s secret of machine learning is dataset quality ultimately determines the quality of results. I could not simply pull all the results from a Google search query because there was too much variation across images. I needed relatively standardized images, individuals with a full outfit with minimal background. The more variation the more challenging the learning task and ultimately more images required to increase accuracy. I built a dataset containing 100 images per category. I restricted the images to women’s attire and combined decades because there were too few image results for men, and relatively few per each individual decade. To further maximize my small data pool, I augmented existing data by applying horizontal flips to images.
Machine Learning
Since I was building an image classifier without tens of thousands of images, I used transfer learning. Transfer learning works off of a pre-trained model and replaces the final classification layers so as to apply it to a new set of images. Selecting the pre-trained model and structure of the final layers are hyperparameters to optimize on. In this case, I selected the VGG16 model with final layers of flatten, dropout (.75), and finally a dense layer (5, activation=softmax). The dropout layer was added to combat model overfitting. My selection process was manual, but advanced methods of Bayesian optimization and genetic algorithms can perform a more robust hyperparameter search. In this case, there was little marginal benefit of these methods because there was a cap on performance given the available data.
Results
The model achieved a categorical accuracy of 73% on the validation set. Accuracy is an appropriate performance metric since the categories were balanced. For more detail see the classification report below:
As this report shows, the major driver of error in the model is the 1940-1950s category, which has low recall (lots of false negatives).
##Image Preprocessing Most of the data I am collecting is rectangular. To fit the VGG16 mode, I need to reshape it into a 244 by 244 square matrix. Without resizing image, this will distort the aspect ratio and potentially hurt the model’s learning. Luckily, Tensorflow has an inbuilt function “tf.resize” that can resize an image without aspect distortion. It does so by shrinking the image and then padding the surrounding areas. The padding needs to be smoothed to avoid hard edges that would confound the model. This padding is computed using three possible functions, Nearest Neighbor, BIliear and Bicubic. I ran a test on these three methods and graphed the results below.
It appears the model using the bicubic function to pad achieved a higher validation accuracy after five epochs. Given the small size of this dataset, I am not confident this result would be generally true, but it suggests it might be a good idea to use tf.resize when working with non-square or variable images sizes
Future Work
In addition to building a larger dataset, focusing on specific elements of clothing could achieve better results. For example, it would be powerful to train the machine to locate pant legs and identify bell bottoms, marking the style as 70s. With enough data, an ML algorithm would learn this on its own, but directed training achieves a better result with fewer images. Training a model to identify pant legs and collars is not trivial, and with time I can build on work that has been done in this area (see DeepFashion).
I could also further expand my data labels and training to other types of categories, like sub-cultures (hippie, punk) or levels of formality (semi-formal, business-casual) This model forms a nice base of work to expand on.


int juliantojd ( int $month , int $day , int $year )
Valid Range for Julian Calendar 4713 B.C. to 9999 A.D. Although this function can handle dates all the way back to 4713 B.C., such use may not be meaningful. The calendar was created in 46 B.C., but the details did not stabilize until at least 8 A.D., and perhaps as late at the 4th century. Also, the beginning of a year varied from one culture to another - not all accepted January as the first month. Caution Remember, the current calendar system being used worldwide is the Gregorian calendar. gregoriantojd() can be used to convert such dates to their Julian Day count.
The julian day for the given julian date as an integer.


All Classes
| Class | Description |
|---|---|
| AccountDetails | |
| AccountDetailsRepository |
This repository represents the detailed information of an account.
|
| Booking |
This is our main class - Every action that is made from an employee or customer will interact with this class.
|
| Booking.BookingType | |
| BookingRepository |
This repository represents the detailed information of a booking.
|
| BookingRequest |
class to store the requierements of a booking that will be stored in an ArrayList for processing by employee
|
| BookingRequest.BookingType | |
| BookingRequestRepository |
This class provides access to the bookingRequests in the database which can be created by customers
|
| ConferenceRoom |
The class Conferenceroom extends the Room Class and its methods
It is used to specify the Room as a ConferenceRoom and sets its specific attributes like the price per hour.
|
| ConferenceRoomBooking |
This class extends the Booking to the kind of room that has been booked, in this case to a conferenceRoom
|
| ConferenceRoomBookingRepository |
This repository specifies the booking for a conference room a little further.
|
| ConferenceRoomRepository |
This repository represents the detailed specified information of a conferenceRoom.
|
| ContactData |
object to store personal data of customer
|
| ContactDataRepository |
This repository represents the ContactData.
|
| Customer |
customer class manages every methode done by the customer and its personal data
|
| Customer.PaymentMethod | |
| CustomerRepository |
This repository represents the Customer.
|
| Employee |
This is the main actor in our application for now.
|
| EmployeeRepository |
This repository holds information on the employee.
|
| HotelRoom |
The class HotelRoom extends the Room Class and its methods
It is used to specify the Room as a Hotelroom and sets its specific attributes like the price per night
Since you cannot create an instance of the Room-class itself the employee can only create instances of the Hotelroom or the ConferenceRoom
instead.
|
| HotelRoomBooking |
This class extends the Booking to the kind of room that has been booked, in this case to a Hotelroom.
|
| HotelRoomBookingRepository |
This repository specifies the booking for a hotel room a little further.
|
| HotelRoomRepository |
This repository represents the detailed specified information of an hotelroom.
|
| Role |
This class implements an early version of a right management system.
|
| RoleRepository |
Represents the roles within the roommanager.
|
| Room |
The class room holds all vital information of the rooms, its size, its category and roomnumber,
i can also tell whether a room is occupied or not.
|
| Room.Category | |
| Room.RoomType | |
| RoommanagerApplication | |
| RoomRepository |
This repository represents the detailed specified information of an room.
|


Dragula
Simple Drag and Drop Example
Just specify the data attribute data-plugin='dragula'
to have drag and drop support in your container.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
Move stuff between containers
Just specify the data attribute
data-plugin='dragula'
and
data-containers='["first-container-id", "second-container-id"]'
.
Part 1
Louis K. Bond
Founder & CEO
"Disrupt pork belly poutine, asymmetrical tousled succulents selfies. You probably haven't heard of them tattooed master cleanse live-edge keffiyeh.
Dennis N. Cloutier
Software Engineer
"Disrupt pork belly poutine, asymmetrical tousled succulents selfies. You probably haven't heard of them tattooed master cleanse live-edge keffiyeh.
Susan J. Sander
Web Designer
"Disrupt pork belly poutine, asymmetrical tousled succulents selfies. You probably haven't heard of them tattooed master cleanse live-edge keffiyeh.
Part 2
James M. Short
Web Developer
"Disrupt pork belly poutine, asymmetrical tousled succulents selfies. You probably haven't heard of them tattooed master cleanse live-edge keffiyeh
Gabriel J. Snyder
Business Analyst
"Disrupt pork belly poutine, asymmetrical tousled succulents selfies. You probably haven't heard of them tattooed master cleanse live-edge keffiyeh
Louie C. Mason
Human Resources
"Disrupt pork belly poutine, asymmetrical tousled succulents selfies. You probably haven't heard of them tattooed master cleanse live-edge keffiyeh
Move stuff between containers using handle
Just specify the data attribute
data-plugin='dragula'
,
data-containers='["first-container-id", "second-container-id"]'
and
data-handle-class='dragula-handle'
.
Part 1
Louis K. Bond
Founder & CEO
Dennis N. Cloutier
Software Engineer
Susan J. Sander
Web Designer
Part 2
James M. Short
Web Developer
Gabriel J. Snyder
Business Analyst
Louie C. Mason
Human Resources


YCee’s album ‘YCee vs Zaheer’ hits 2m streams - The Nation Newspaper
‘YCee vs Zaheer’, the latest album of singer and rapper, Oludemilade Alejo aka YCee, has been streamed over two million times.
News Agency of Nigeria (NAN) reports that YCee excitedly shared the news on his instagram page @iam_ycee.
The long-awaited debut album entitled ‘Ycee vs Zaheer’ was released on Nov. 8 and has steadily become a fan favourite in the last couple of days.
The project comes as a follow up to his 8-track body of work ‘First Wave’ (2017) and ‘Late Night Vibrations’ in 2018.
The two-dimensional album featured collaborations with Davido, Phyno, and Niniola.
Among the songs contained in the 15-track project are `Its Amazing’, ‘Wahala Dey’, ‘Bossing’, ‘Chocolata’, ‘Cheque’ and ‘Dakun’.
Others are ‘Vibing’, ‘Mo Salah’, ‘So Nice’, ‘Mine’, ‘Love Like That’, ‘Bassline’, ‘Dada’, ‘Vacancy’.
The album also had Ycee engage a squad of fiery producers including Adey, JayBidz, Ballertosh, Fanatix and BeatsbyKarma.
He also worked with Syn X, Krizbeatz, Jay Popping, Buzzin Producer, AP Da Don, TwoSeven, Elmore, and KO.
READ ALSO: Falz, Zlatan, Skiibii, Ycee honour MTV BASE at 14
Speaking on the idea behind the album’s title, the Headies-nominated singer had said that his choice of ‘Ycee vs Zaheer’ was a deliberate attempt to display his singing (Ycee) and rapping (Zaheer) side.
YCee rose to limelight after his single ‘Condo’, which features vocals from Patoranking, earned him two nominations at the 2015 Nigeria Entertainment Awards.
He was also nominated for Best Artist in African Pop at the 2015 All Africa Music Awards.
In October 2016, Ycee signed a record deal with Sony Music, but terminated his contract with the label in February 2018.
(NAN)


{% extends "page.html" %} {% block stylesheet %} {% if mathjax_url %} {% endif %} {{super()}} {% endblock %} {% block bodyclasses %}notebook_app {{super()}}{% endblock %} {% block params %} {{super()}} data-base-url="{{base_url | urlencode}}" data-ws-url="{{ws_url | urlencode}}" data-notebook-name="{{notebook_name | urlencode}}" data-notebook-path="{{notebook_path | urlencode}}" {% endblock %} {% block headercontainer %}
Kernel
To get started, you have to import plotly, pandas, pyspark, pyspark SQL and its types. The reason you have to use pandas is because we will convert the Spark dataframe into pandas dataframe.
Next you need to create the SparkContext as sc
and SQLContext as sqlContext
. Dataframe is only available as SQLContext.
To load a text file in your local filesystem or HDFS, you can use sc.textFile
and point to the path of that file relatively to your current notebook. Now to convert the content within the text file to Spark Dataframe and then Pandas Dataframe, there are several steps.
myFile.map(lambda l: l.split(","))
.lines
array, conver that to a list using lambda function again. This is required in order to create Spark Dataframe later.fields
variable which is your top header. The fields must be StructType because that is how Spark Dataframe requires as the input parameter.sqlContext.createDataFrame(coords, fields)
toPandas()
pdf
Pandas Dataframe using pdf.head()
You need to pass the coordinates of x
, y
and z
to Plot.ly by creating scatter3d
and mesh3d
plot types. Since you already had the Pandas Dataframe pdf
, all you need to do is to create a Python dictionary object from it.
Plot.ly needs to understand how you want the layout to look like. So you have to include information such as title and scene axis.
Now once you have all of those objects created for scatter, clusters and layout, you must come up with a final fig
object.
The final step is to plot the 3D chart by calling py.iplot
. This will inject an iframe
element into your current notebook.
This is an optional step but it is a must if you want to re-run another notebook with SparkContext declaration. The reason is that you cannot have more than one SparkContext in the same JVM. Plus it's better to stop one and restart fresh.


To become a world class event planning organisation that will see to the full realisation of our clients events and give them the kind of satisfaction they deserve.
What i love about prudies touch is how their workers interact with you before, during and after an event .
Prudies touch is soo good at making birthday parties. They plan all our birthday parties for us. . Love it Prudence Attablayo .Keep it u
I tell you, Prudies touch can plan an event for even if youre in Ghana and the event will be held at Anambra state in Nigeria .. Thumb up
Happy Customers
Complete Projects
Years in the Market
Ashongman Estates - Accra , Ghana
<EMAIL_ADDRESS>+233 274454123


9 Working with SLiM data
9.1 Overview
A lot of the power of SLiM (and simulations in general) is that it is relatively cheap to keep track of a lot of data, which would be impossible in the field. SLiM’s output is extremely customisable, so anything that you keep track of during a simulation, you can output to a file. But should you? Outputting everything you are modelling as text will result in huge files which are difficult to work with, and contain irrelevant data. With more frequent sampling and more data, you’ll end up with huge plaintext files that R or Python will have a hard time reading. You could upload this to a database, but this will incur large speed penalties when trying to analyse your results. In large experiments, it is important that you only keep track of what you need to, and sample as little as you can get away with. The importance of this decreases the smaller your experiments, but it is still something to keep in mind, not only for your hard drive’s sake, but also your simulation’s speed.
9.2 An example of saving space in custom SLiM output
The examples below are from the output in Chp5-1_1T.slim
. Here, we take a variety of quantitative
and population genetics statistics as output, saving them every so many generations:
420 Mfile = paste(sim.generation, asString(seed), modelindex, meanH, VA, phenomean, dist, w, deltaPheno, deltaw, sep=",");
421 writeFile(outName, Mfile, append = T);
Mfile
contains all the statistics we are measuring. We need the timepoint and model information to identify what all this data
will belong to, but we don’t need every predictor variable! This is the purpose of modelindex
, as explained in Chapter 5.
modelindex
is unique for each parameter combination, and hence describes all of those parameters in a single value. This saves
a lot of space for the final output, as we are removing upwards of 3 columns (depending on how many parameters you are adjusting).
You could similarly save space by saving the seed as the index of seeds in your seeds.csv
file, rather than the actual 32-bit seed
value, however I found this unnecessary.
Not only does this save space, but it also saves processing power, as SLiM doesn’t need to fetch information on all of these parameters
every time it stores output. While this is a tiny amount of time individually (a modern CPU can fetch a variable from a memory address
in less than 1 nanosecond, although SLiM introduces overhead to this so it won’t be nearly as quick), in large experiments this can
add up, especially if you are changing many parameters and sampling often.
As mentioned in Chapter 7, as well as measuring how long your experiments will take, it can be a good idea to measure how large your output files will be, particularly if you know they are likely to be large. This will allow you to better dial-in your sampling rate according to the amount of space/RAM you have available to do analysis, and the resolution of the data you are collecting.
A much larger output is also in my example script:
306 for (mut in muts) {
...
317 mutsLine = paste(sim.generation, asString(seed), modelindex, mutType,
mut.id, mut.position, mut.originGeneration, mutValue,
mutChi, mutFreq, mutCount, "NA", sep = ",");
}
Here, a line is created for each unique mutation existing in the population. This output quickly grows to large sizes. Hence, it is sampled less often than the other output (line 420), to ensure the simulation is fast, and that the data isn’t too big to handle.
9.3 Compression
Another option is to compress your output. SLiM does have an option to compress custom output (via the writeFile(compress = T)
argument),
however keep in mind this will raise the memory footprint of your model. As the documentation says, "If the compress option is used in conjunction
with append==T, Eidos will buffer data to append and flush it to the file in a delayed fashion (for performance reasons), and so appended data
may not be visible in the file until later – potentially not until the process ends (i.e., the end of the SLiM simulation, for example)."9
In English, that means that SLiM holds onto the data that would be written to the file until it has time to decompress the file, add the new output line/s,
and recompress the file. This probably won’t happen until the end of the simulation, however you can force this process to happen using the
function flushFile()
, which will stick all the ‘waiting-to-be-written’ lines of output onto the file and clear the queue. For example, if you are
appending output to a file every 50 generations, and you wanted to compress this output, you could use flushFile()
to keep your RAM usage under control
by calling flushFile()
every 500 generations or so.
9.4 Footnotes
Haller, B.C. (2021) Eidos: A Simple Scripting Language, Version 3.6, pp. 71, URL: http://benhaller.com/slim/Eidos_Manual.pdf↩


THE DREAMLIFE OF ANGELS A film review by Steve Rhodes Copyright 1999 Steve Rhodes RATING (0 TO ****): **
In THE DREAMLIFE OF ANGELS (LA VIE RÊVÉE DES ANGES), Isa (Élodie Bouchez) and Marie (Natacha Régnier) are two twenty-year-old women who lead an itinerate lifestyle. Rarely with much money, they go from one odd job to another. They meet at a sewing job, something for which neither of them is particularly well suited. Isa, who carries all of her possessions on her back, talks Marie in letting her stay in the apartment in which Marie lives temporarily until its owners come back. Since both of the owners are in a coma after a car accident, it isn't clear when, if ever, they will return.
The bleak and surprisingly thin story has the two women form a modest bond due to their similar circumstances. Besides being without funds, both grew up in unhappy homes -- Isa because her parents broke up and Marie because her parents didn't.
In a story in which almost nothing happens until the last scene, we do learn much about Isa's smoking techniques. First-time director Erick Zonca, who shares the writing credits with Roger Bohbot, apparently believes that people reveal much about their character by the exact manner in which they smoke. Although both women share a nicotine habit, Zonca uses repetitious tight shots to dwell on Isa's proclivity.
Isa, with her fingernails always partially covered with old nail polish, likes to grip her cigarettes as if she is trying to crush them.  After every third puff, she ritualistically picks off a tobacco particle from either her lip or tongue. I have yet to decode the precise significance of these mannerisms, but given the screen time devoted to them, they must contain important symbolism.
The title is essentially a misnomer. The story has little to do with angels or dreams, although a subplot does have Isa sitting in the hospital with the apartment owner's comatose daughter and reading from her diary.  A troubled and angry woman, Marie acts like she is going to slug the men she meets but ends up going to bed with them instead. Sex with Marie can be rather like a wrestling match.
Character-driven movies like this succeed based on how compelling the characters are, and neither of the leads here ever manage to draw us into the story. The director makes especially uninspired choices in the staging. Besides his obsession with the intricacies of smoking, he also features a segment on the washing and drying of a backpack. The result is that, at the end, when the film finally tries to engage the audience, we've long since lost interest.
"You've been moping around all week," Marie complains to Isa during one of their mild spats. This is the exactly the problem with the movie. It mopes around most of the time with not much to say. Oh well, at least the two actresses do show promise even with such bland material.
THE DREAMLIFE OF ANGELS runs 1:53. The film is in French with English subtitles. It is not rated but would probably be an R for sex, nudity and profanity. The movie would be fine for older teenagers.
Email<EMAIL_ADDRESS>Web: www.InternetReviews.com
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


Steve Bruce makes John McGinn to Manchester United declaration and reveals golf trips that helped trump Celtic
Aston Villa midfielder has been rated as high as £50million and has attracted interest from Old Trafford.
by Simon BirdJohn McGinn has been told he’s Manchester United quality – by the boss who signed him for a bargain.
The Aston Villa midfielder is a £50million-rated buy and being monitored by Ole Gunnar Solskjaer.
But ex-Villa boss Steve Bruce has revealed how he lured McGinn to the Midlands from Hibs in 2018 for £2m thanks to some rounds of golf at a former Ryder Cup venue.
He said: “We nearly didn’t sign him because we couldn’t afford £2m. But we whipped him away from Celtic just at the right time. I always knew he’d be very good but he’s surpassed expectations.
“How we kept him away from Celtic I don’t know because his grandfather was the chairman.
“It took a couple of games of golf at The Belfry with his dad until we could muster the money together. I am delighted for the kid because he is a smashing lad.”
Bruce rates him as one of his best cut-price signings. High praise indeed given he landed Liverpool’s Andy Robertson for £2.85m at Hull.
Bruce said: “He has to be one of my best-ever signings because he has a determination to do well.
“It took him a minute to win over the supporters at Villa when I was manager because he crashed into a tackle, sprayed a 50-yard pass and had a shot in his first few minutes.”
Villa say it would take an eye- watering sum to lure him away mid-season but Bruce added: “Man United? From what he has done in 12 months, he can only improve. He is that level, yeah.”


spinal tumors {border-style px;} schwannoma #ffffff;} cervical extradural tumor cord posterior schwannomas Case case left px; report swelling {font-family Extradural Spinal font-size neurological patient rare Fig. double; sensory surgical triangle Antoni Medical Neurosurg border-color border-width clinical findings motor nerve patient. pediatric population review solid; tissue {font-style {font-weight (Fig. -year-old College Med Pediatric bold cases common courier; em; imaging intramedullary intraspinal involved management mass muscle neck. postoperative provided pt;} resonance seen sheath symptoms total well-defined


|
This view contains site specific identifiers usually entered as part of EMR configuration.
#
|
Name
|
Type
|
Description
|
Options
|
1
|
FacilityID
|
Integer
|
System assigned unique ID for the facility
|
8030011, 755
|
2
|
SiteCode
|
Text
|
Government or program assigned ID for the facility
|
|
3
|
FacilityName
|
Text
|
Name of the facility
|
|
4
|
FacilityOwner
|
Text
|
MoH, Private
|
|
5
|
ImplementingPartner
|
Text
|
AIDSRelief, PACT, KARP
|
|
6
|
CountryID
|
Text
|
Program provided country ID. May not be globally unique
|
|
7
|
Country
|
Text
|
Country Name
|
|
8
|
Region
|
Text
|
May refer to province in some countries
|
|
9
|
District
|
Text
|
District Name
|
|
10
|
PepfarStartDate
|
Date
|
Date EP program started at facility
|
|
|


Search
Add Image to Database
Results
Add Image to Database
×
Select Image
*
Description
*
Category
Save


WaitComponent(waitTime: Float)
Delays the execution of other Components. The executing system must exclude entities with the WaitComponent. After the wait time is elapsed, the WaitComponent is removed and the execution of other components can continue.