Search

Light Trapping Nano-Antennas That Could Change The Application Of Technology

Travelling at a speed of 186,000 mi/s, light can be extremely fast. Even Superman, the fastest creature on Earth, cannot travel at the speed of light. Humans have shown several times that they can control the direction of light by passing it through a refractory medium. But is it possible to trap light in a medium and change its direction just as you can trap sound in an echo device? Before now that possibility was theoretical but new research has shown that this could be practical. Since light is useful for information exchange and so many applications, the ability to control light, trap it or even change its direction could have several applications in science and technology.

outline from light trapping device
 

In a recent paper published in “Nature Nanotechnology”, some Stanford scientists who were working at the lab of Jennifer Dionne, an associate professor of materials science and engineering at Stanford University, have demonstrated an approach to manipulating light which has been successful in its ability to significantly slow the speed of light and also change its direction at will. The researchers structured silicon chips into fine nanoscale bars and these bars were used to trap lights. Later, the trapped light was released or redirected.

One challenge the researchers faced was that the silicon chips were transparent boxes. Light can be trapped in boxes but it is not so easy to do if the light is free to enter and leave at will just as you find in transparent boxes.

Another challenge that was faced by the researchers was in manufacturing the resonators. The resonators consist of a silicone layer atop a wafer of transparent sapphire. The silicon layer is extremely thin and it has the ability to trap lights very effectively and efficiently. It was preferred because it has low absorption in the near-infrared spectrum which was the light spectrum that the scientists were interested in. This region is very difficult to visualize due to inherent noise but it has useful applications in the military and technology industry. Underneath the silicone layer is a bottom layer of sapphire which is transparent and the sapphire are arranged in wafers. Then a nano-antenna was constructed through this sapphire using an electron microscopic pen. The difficulty in etching the pattern for the microscopic pen lies in the fact that if there is an imperfection then it will be difficult for it to direct light as the sapphire layer is transparent.

The experiment would be a failure if the box of silicon allowed the leakage of light. There should be no possibility of that. Designing the structure on a computer was the easy part but the researchers discovered the difficulty lay in the manufacturing of the system because it has a nano-scale structure. Eventually they had to go for a trade-off with a design that gave good light trapping performance but could be possible with existing manufacturing methods.

The usefulness of the application

The researchers have over the years tinkered with the design of the device because they were trying to achieve significant quality factors. They believed that this application could have important ramifications in the technological industry if it was made practical. Quality factors are a measure of describing the resonance behavior involved in trapping light and in this case it is proportional to the lifetime of the light.

According to the researchers, the quality factors that were demonstrated by the device was close to 2,500 and if you compare this to similar devices, one could say that the experiment was very successful because it is two times order-of-magnitude or 100 times higher than previous devices.

According to Jennifer Dionne at Stanford University, by achieving a high quality factor in the design of the device, they have been able to place it at a great opportunity of making it practical in many technology applications. Some of these applications include those in quantum computing, virtual reality and augmented reality, light-based Wi-Fi, and also in the detection of viruses like SARS-CoV-2.

An example of how this technology could be applied is in biosensing. Biosensing is an analytical device used for the detection of biomolecules that combines a biological component with a physicochemical component. A single molecule is very small that essentially it is quite invisible but if light is used as a biosensor and passed over the molecule hundreds or even thousands of times, then the chances of creating a detectable scattering effect is increased, thereby making the molecule discernible.

According to Jennifer Dionne, her lab is working on applying the light device on the detection of Covid-19 antigens and antibodies produced by the body. Antigens are molecules produced by viruses that trigger an immune response while antibodies are proteins produced by the immune systems in response to the antigens. The ability to detect a single virus or very low concentration of multitudes of antibodies comes from the light – molecule interaction created by the device. The nanoresonators are designed to work independently so that each micro-antenna can detect different types of antibodies simultaneously.

The areas of application of this technology is immense. Only the future can predict the possibilities when other scientists start experimenting with what was discovered. I think this innovation is a game changer.

Materials for this post was taken from the Stanford University website.

A Concise Guide To Python Loops

In a post this week, while discussing control flow in python, I wrote about repetitive control structures in python which consist of the python while and for loops. But I received some text message where a reader said my post was not concise enough; that I left off some features of python loops. I agreed with him. This was because my focus was just in showing how control structures work in python and not on showing all the features of python loops. So, in this post, I have decided to write a concise guide on python loops.

python while loop and python for loop
 

As I said earlier in the other post, when you want to repeatedly iterate over some block of code you use loops. In python, you can either use a python for loop or a python while loop. After showing examples of both loops, I will then concisely explain what situations both loops can be used that makes them similar and different.

The python for loop

In order to be more concise and cover all situations, I will use the syntax of the documentation reference in defining a python for loop.


for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]

This python for loop syntax states that a for loop is denoted by the “for” keyword. Also, on evaluation of the iterable that would be used in the for loop, expression_list, an iterator is created consisting of all the items to be used in the looping construct. Then for each iteration, the target_list is bound to each of the items in the expression_list iterator, and it will be used in the suite which is the block of code that is to be repeated. A python for loop can have an optional else clause. The else clause, when denoted, is called when the loop has completed all its iterations.

Now a picture is worth a thousand words. Let’s illustrate the syntax above with an often used syntax:


# please note that the else clause is optional
for variable in iterable:
    block of code to execute
else:
    block of code when for clause ends    

Just as in the documentation’s syntax, the variable is assigned each item in the iterable during an iteration until the iteration ends. Most times, the variable is used in the block of code to execute.

Let’s show how the iteration works using a python for loop example with an iterable, this time a list, and printing out each iteration of the list to show how they are passed to variable.

When you run the code above, you can see that each item in the list is printed out in the block of code. This is because for each iteration, the item variable is bound to the first fruit, then the next fruit, and so on subsequently.

What if for each iteration we want to do something with the items, like multiply each item in the sequence. Here is code that shows you how.

You can see that the python for loop iterates through each of the numbers and prints them out.

Now, let’s show how the often ignored else clause can be used. When the loop finishes its iteration we can specify an else clause with a block of code that will be executed. The else clause in a for loop is similar to the else clause in a try statement and not to the else clause in an if statement.

I told you this promises to be a concise guide. So, I will show one more example of the use of an else clause. What if we had a for loop that when a condition is satisfied, it breaks out of the loop but has to execute another block of code after it breaks out of the loop. For example, imagine having some numbers in a range, like 1 to 10, and writing a function that states whether each number is a prime or a composite. A prime does not have a factor between 2 and the number, except 1 and the number itself. So, using this property we will factor all the numbers from 2 to that number and use the result of remainder division to state whether a number is a prime or a composite. I will use two loops for this example. See how the else clause is used to achieve this effect.

Notice that the else block is triggered when the second for loop goes to completion because the number is not a composite number. Anything that is not a composite is prime. But if it is a composite number, we break out of the loop to the outer enclosing loop to start another outer iteration.

There is something I introduced in the above code which I have not talked about. That is, using the python range function in a for loop to iterate over numbers. Yes, the range and for loops come in very handy when you want to iterate over numbers in python for loops. Use them at your convenience. The syntax of a range function is: range(start, stop[, step]). The start is the number to start the iteration from. The stop is the number at which to stop the iteration. Stop is not included in the iteration. The step signifies how you pick the numbers, maybe you want to pick every second number from the start of the range etc. When there is only one argument to the range function, it is understood to refer to the stop. The default for start, which is 0, is assumed, and the default for step, which is 1, is assumed. When there are two positional arguments, it is understood that the first is the start and the second is the stop. Then the default for the step, 1, is used. Note that you cannot make step to be zero or it will give a ValueError. To illustrate, let’s use examples.

The range function is a handy tool to use with the for loop when you are dealing with numbers. You use it to create a sequence of numbers to be used in the iteration directly, as we did in the for loop above. Or you can use it to create a set of integer indices that can be used on the sequence itself. Let’s show an example of using it to create indices for use in the iterable. Here you create the argument for the range using the length function called on the iterable. I discussed about this in an earlier post on how powerful the length function is. Now, for an example.

Item variable above are integers created by the range function as indices to the fruits list.

Finally, before I end the discussion on for loops, I have to tell you that for loops can be nested. I showed an example in the loop above that looks for prime numbers. But another example of a nested for loop would not be bad.

I promise to be concise, right? So, let’s take on python while loops.

What are python while loops?

The while loop or while statement is used for repeated execution of a block of code as long as an expression is True. Here is the syntax of a python while loop according to the documentation:


while_stmt ::=  "while" assignment_expression ":" suite
                ["else" ":" suite]

You can see from the above that you begin the while loop with the while keyword and this is followed by the expression you want to evaluate for whether it is True or False. Note that the expression must be a Boolean expression. As long as the expression is True, the while loop will continue executing the statements in the suite or block of code. Also, notice that a while loop also has an optional else clause. This else clause can be used to signify block of code you want to run when the while loop finishes running or when the expression evaluates to false.

The common syntax for python while loop used by many authors is:


# the else clause is often not used. Optional
while condition_is_true:
    body_of_code
else:
    body_of_code    

This is the flow of control of a while loop. First, the condition is checked whether it is True. If it is False, the while loop is not executed but flow of control moves to the next statement in the code. If the condition is True, the body of code in the while loop is executed until it becomes False.

Note that if the body of code in the while loop is executed and the condition does not become False during the time the loop is running, you will enter an infinite loop. That is, a loop that never ends. If you enter an infinite loop, just press CTRL+C on your machine and it will stop execution of the loop. But you can prevent infinite loops.

How to prevent infinite python while loops.

To prevent infinite loops occurring in your python while loops, you need to use a counter at the condition or Boolean expression. Then you have to initialize the counter before the while loop and increment or decrement the counter in the body of the loop.

Now, let’s do all this with some examples. First, showing the use of a counter in the condition of the loop to test for True.

Let’s take some points from the code above. But, first I will encourage you to run it to see that it works. First, before the loop we initialized the counter to 1, our starting number. Then we used the counter to test for the condition that we have not gone beyond the last number, 5, by saying we want counter to be true when it is less than 6. Then in the body of the while loop we incremented the counter so that on each iteration the counter keeps moving towards 5 and when it moves beyond 5 to 6, the condition becomes False so we exit out of the loop. What if we had not incremented the counter in the body of the loop? We would have entered an infinite loop. If we had not initialized the counter before the loop condition, we would have gotten a NameError exception. I want you to test these two error conditions on your own machine.

Now, if we do not want to use a counter, we could use a variable that is bound to a Boolean value in the condition of the while loop. We need to initialize the variable also before the while loop is entered. Then in the body of the while loop we change the switch for the variable so that the condition can become False when we want the loop to stop execution. Here is an example.

Notice that I am doing the same calculation but this time using a variable that is bound to a Boolean value. We initialized the variable before the while loop and makes sure it is True in the condition. Then in the body of the loop, when our condition is satisfied and we want the loop to stop execution, we switched the variable so that the condition becomes False.

There are two more statements about loops that need to be considered. The python break and continue statements. But I don’t want to repeat myself. Programmers aim to reuse code, so I would encourage you to go to the post on control flow where I discussed break and continue statements in loops. I believe I was very concise in explaining those concepts in that post. You can find the explanation at the end of the post.

Now finally, the similarities between for loops and while loops along with their differences.

Similarities and differences between python while and for loops.

First, their similarities. The basic similarity between a while loop and a for loop is that you can end either loops early via a break statement. Whenever you call a break statement on either loop, it stops execution of the loop enclosing the break statement.

There are three differences I have noticed between the two loops:

A python for loop has a finite number of iterations and you can know how many iterations it will perform. A while loop might have an infinite number of iterations and you might not be able to count how many iterations it will go through.

Although both loops can use a counter, the counter for a while loop must be initialized before the loop and then incremented or decremented in the body of the loop.

You can rewrite a python for loop using a python while loop but you might not be able to rewrite a while loop using a for loop except in some cases.

So, I can now rest in peace. That is my concise guide to loops in python.

Happy pythoning.

An Unstructured, Random Python Cipher That Seems Unbreakable

Today, we will be cracking codes with python. While researching on this post, I came up on an article about Caesar’s cipher. Caesar’s cipher is a means of encrypting messages using a mapping from the original alphabets to the encrypted alphabets with the original alphabets shifted by some keys either to the left or the right to produce the encrypted alphabets. The author said that Caesar’s cipher, which was one of the earliest forms of cryptography, could be broken by a brute force method. I said to myself: “That’s cool. It could be broken because Caesar’s cipher has a key with a structure. What about if the key has no definite structure?” So, I decided to write a program that is inspired by Caesar’s cipher but with a random key that has no structure. Rather than use the python chr and ord functions, I decided that a better way for my concept to work was to randomize a translation table. But to have a random translation table, I needed to first create it.

 

keys to a cipher in python

How do you create a translation table that has no structure when mapping from source to destination strings and is random? Well, before I begin explaining how, I should explain the functions we are going to use. The functions are python’s randint, maketrans and translate functions.

The python randint function.

The python randint function is a random number generator in python and one of the methods of the python random module. It generates a random integer each time it runs. To use it, you have to import the python random module. The syntax of the randint function is random.randint(a, b) where randint generates integers between a and b inclusive. If you want an indepth coverage of the python randint function and other functions of the python random module, you could do well to read it up on an earlier post. So in my solution today, I will be using the randint function to generate python random numbers.

The next function is the maketrans function.

What is the python maketrans function?

Python has two types of maketrans functions - the static byte.maketrans method and the static str.maketrans method. The earlier belongs to byte objects and the latter to string objects. Both are used to make translation tables for mapping characters.

  • Bytes.maketrans:
  • The syntax is bytes.maketrans(from, to). It will map each python character in the from string of bytes to its equivalent python character in the to string of bytes while making a translation table to be used by the python translate function. From and to must be bytes objects with the same length. To create a translation table that maps ‘a’ to ‘e’, ‘b’ to ‘f’, and ‘c’ to ‘g’, in bytes, we could write the following code:

    
    original = b'abc'
    end = b'efg'
    translation_table = bytes.maketrans(original, end)
    

    When we have a translation table, the work of doing the actual translation is nearly complete.

  • Str.maketrans:
  • The syntax is str.maketrans(x[, y[, z]]) where y and z are optional arguments. When using the python str.maketrans function you are making translation tables that maps python characters or Unicode ordinals to other python characters, Unicode ordinals or None. Note that Unicode ordinals are mappings of characters as integers. For example, ordinal 97 is character ‘a’ while ordinal 98 is character ‘b’.

    When only x is used as the argument in the python str.maketrans method, you must supply a dictionary to str.maketrans method to make a translation table. Note that all translation tables are dictionaries that maps the source to the destination. Here is an example:

    Like before, we are mapping ‘a’ to ‘e’, ‘b’ to ‘f’, and ‘c’ to ‘g’. In the translation table, the Unicode ordinals for the characters are used to identify the characters.

    What if you specify two parameters to maketrans i.e x and y. When you do so, both x and y must be python strings of equal length. You need to specify a string that contains the keys in order for maketrans to properly understand how to create the translation table. Maketrans will create a translation table mapping characters in x, the source, to characters in y at the same index. An example is below:

    If you want some characters to be mapped to None in the translation table, then you have to specify the third argument, z, when calling str.maketrans. Any character in z is mapped to None. Here is an example where d is mapped to None. Any character mapped to None is deleted during the translation of the actual message.

So, I believe you now understand how to create translation tables and you know that the translation tables uses the Unicode ordinals for the characters. Therefore, instead of specifying characters, you could just write out the Unicode ordinals if you know them.

The next step is to do the translation. You use the python translate function to do the actual translation.

How to use the python translate function.

To do the actual translation from the translate table, you use the python translate function. There are two types of python translate functions, the bytes.translate and str.translate, but I suggest you stick to just str.translate because most of the messages you will be translating will be python strings.

The syntax for str.translate is str.translate(map) where str is the message you want to translate and map is the translation table you will be using to do the mapping of the characters in the message. Notice from above that the translation table is a dictionary of Unicode ordinals to Unicode ordinals, strings, or None.

What the translate function does is to take each character in the message, look for its corresponding key in the translation table. If it exists, it replaces that character in the message with its value in the translation table. If the character does not exist in the translation table, the character in the message is left as it is. If in the translation table the character is mapped to None, it is deleted in the message.

Now, that’s a mouthful. Let’s illustrate all the above with examples.

First, let’s translate a message containing the characters in the source above. For example, supposing our message is ‘abccbaaaab’, how would it be translated?

When you run the above you would notice that ‘abccbaaaab’ is translated to be ‘efggfeeeef’ since we are replacing all ‘a’ with ‘e’, all ‘b’ with ‘f’ and all ‘c’ with ‘g’.

Let’s take another example where some characters in the message do not appear in the translation table and also some characters in the translation table are mapped to None.

If you look closely at the code, you will notice that the message has four characters but the translation has just three characters. ‘a’ and ‘b’ were translated as per the translation table to ‘e’ and ‘f’ respectively. In the translation table, ‘d’ is mapped to None so in the translation it is removed. While there is an ‘e’ in the message but there is no key ‘e’ in the translation table so the ‘e’ character is left as is, untranslated.

So, we have what it takes for us to do our unstructured, random python cipher.

This is the source code. You can run the code before understanding the logic stated below just to see how it works. Run it more than once and see that each time you get a different encryption scheme.

This is the logic behind the code. We will first create our source string for the translation table. That will be all the lower case alphabets. We will then cast this source string to a list and use it as a list of values we are going to use for the destination string or replacement string. Since all the alphabets are 26 characters, we enter a loop in line 7 which will create a replacement string 26 times. For each iteration of the loop, we will create a random index between 0 and 25. The index variable serves as an index to the values_list which will be used to create the replacement strings or destination strings. When we have a random index, we will then check if that index has a value in the values_list (line 9). If it has a value, we place that value in the destination_list, adding it as a stack. That means the first value will be the replacement for ‘a’ in the source string. After placing that value in the destination_list, we then substitute its corresponding value in the values_list with None; to tell the code that we have come to that index. Each time that the index gets a value in the values_list that is None (we have already used it), it moves one step in the values_list modulo 26, looking for an unused value in the values_list until it finds one. When it finds one, it stops looking (lines 12 -19). This step of stepping through the values_list looking for a value makes the arrangement of the replacement strings unstructured or without any pattern. That makes it difficult to use a mathematical formula to crack the code. I was thinking about this when I wrote a blog post on the unbreakable code and internet security that describes one-way functions. One-way functions are unbreakable codes; they are functions that go one way and cannot be reversed. Making my replacement strings unstructured mimics this behavior.

When the destination_list is completely populated, we then convert the list to a string (line 20). So, right now, we have our source and destination or replacement strings which makes it possible to create the translation tables for encryption and decryption. (Lines 24 – 28). With the translation tables created, we do the actual encryption and decryption using a specified message and voila, it works. (Lines 31 – 36)

You will notice that each time you run the code, you will get a different encryption scheme because the translation tables are randomized. That makes it difficult to break. What anyone using the code would have to do is to run it once, save the state of the translation tables in a database and use the translation tables for encryption and decryption. The weak point of my code is protecting the translation tables from hackers laying a hold on it, otherwise I think it would be very difficult to hack this scheme.

I challenge anyone to hack it without peeking at the translation tables.

If you want the source code for the unstructured, random python cipher, you can download it here.

Matched content