Friday 29 January 2016

Drawing a treasure map.

I'm no artist. Let's get that out of the way straight up. But I do like to try new things.
A few months ago while proctoring a class, I got it into my head that I really must start drawing some old style maps.
I had no idea what I was doing coming into this and I still have relatively no idea, but each step is progress. I thought, it's a relatively cheap hobby to dive in and out of and it might sate my antique map fetish for another decade.
So off I went. I started to scratch out some images in my ideas notebook I carry around everywhere next to me and then started to  figure out how to draw mountains, trees and sand dunes.
Once I thought I was read to continue, bought a watercolour pencil set, a book of watercolour paper and used my gel pens from work. Total cost? Probably no more than $10.
The aged look was quite simple. I just made myself a cup of teach and when it had finished seeping, I took it out and rubbed it over my paper. I think the effect is kinda cool.

The result: Okay for a first go. I am particularly happy with the ship and the sea monster. I think I did okay with the shape of the island and the shading but the mountains and hills just seem to lack depth. I was not a fan of how the shipwreck turned out and the the cliff face stands out like dog's balls. Halfway through the map making I discovered a brown(sepia) gel pen that I wish I had found earlier. But the good news it that I abused the hell out of it in my next drawing.

Sunday 31 May 2015

Python 3 - New File Creator Module

So I have decided to create a module for file saving for my Python 3 project and though I would share it.
My problem is that I wanted more control over how I handled file saving rather than let a user open a file dialog window like tkFileDialog and put things in places I didn't want them to go.
I also didn't want them to use a wrong source file. In my program I have a JSON file pre-set for input if they save a blank JSON file or some other file extension, the program with break.
Finally, I had an image file that went with my JSON file. The user would select the file from anywhere, which is fine, and then I thought it would make life easier for me to save it with the same file name.

Enter the new_file module. Its main tool is the new_file object. It allows you to quickly choose:

  • a file source
  • a file name for your new file
  • the location you want to put the file in
  • the file type
It also cleans the name of the file just in case you have a user putting in the name and they are a little crazy about white space and symbols that will stuff up your files.
Lastly it checks if the file already exists and appends a file with a number so you don't copy over over a file.
The new_file module also has another object, the extra_file. You can choose to apply this object after using the main new_file object. It allows you to quickly save a file using the same name.
So now instead of 50+ lines of code you only need one or two.

You can get the file on Github here.

Below is a copy of the documentation I have written to give you some more detail.

# new_file_creator
Python 3 module for creating new files where you need a little more control over file location and file copy template

:mod:`new_file` -- New File Creator
===================================

.. module:: New File
   :synopsis: Sometimes you want a little more control over your source file and where you want to save it rather than use something like tkFileDialog where the user has the choice over the location.
The new_file module allows you to direct to the location of the template file, choose the file name and select the directory it is in. It also allows you to quickly save child fills with the  same file name.
.. moduleauthor:: Scott Donald

FEATURES
      new_file object
         Use this file to save a file in a directory.
       
         new_file(file_to_copy, new_file_name, new_file_path, file_type)
       

  •          *file_to_copy - The template file you want to copy. e.g. 'tmp.txt' if it is in the same file path or 'c:/Users/Batman/Documents/tmp/txt'
  •          *new_file_name -The name you want to give your new file. e.g. 'Harry Botter'
  •          *new_file_path -The directory you want your file in. If you are putting your file in the same location as your program, leave it blank (e.g. ''). If it is in a child directory just add the file location (e.g. 'JSON/' or 'Images/'). If your folder location lies outside your program you will need to use the full path (e.g. 'c:/Users/Batman/Documents/tmp/txt') 
  •          *file_type - The file extension of your file (e.g. 'jpg', 'txt','json','wav').

       
      extra_file object
         Use this file to save a file using the same name that was created in the new_file object.
       
         extra_file((file_to_copy, directory, file_type))
       

  •          *file_to_copy - The template file you want to copy. e.g. 'tmp.txt' if it is in the same file path or 
  •                         'c:/Users/Batman/Documents/tmp.txt'
  •          *directory - The directory you want your file in. If you are putting your file in the same location as your program, leave it blank (e.g. ''). If it is in a child directory jsut add the file location (e.g. 'JSON/' or 'Images/'). If your folder location lies outside your program you will need to use the full path (e.g. 'c:/Users/Batman/Documents/tmp.txt')
  •          *file_type - The file extension of your file (e.g. 'jpg', 'txt','json','wav').
  •          NOTE - This file uses the directory name from the new_file object.

       
      getting your file once it is loaded
         You can call your newly created file by:
         new_file.new_file.created_file 
         #For your main file.
       
         new_file.extra_file.created_extra
         #For your child files.
   
 
EXAMPLE 1- Single File Save
       
import new_file
chicken = new_file.new_file('blank.json','Jeeves #Smelly B^%#um34','JSON/', 'json')
       
         PROCESS

  •          *CLEAN THE FILE NAME - if the user creates the file and goes to town on symbols and spaces this will clean it up.
  •             *Get's rid of whitespace and joins it with and underscore
  •             *matches any alphanumeric character and the underscore only and joins it back into one string. 
  •             *Cut filename length to 150 characters if it is over. In our example 'Jeeves #Smelly B^%#um34' will be transformed to 'Jeeves_Smelly_Bum34'
  •          *CHECKS THE IF FILE EXISTS - checks if file already exists in new directory. 
  •             *Searches for file. 
  •             *If it exists it creates a copy of the file. For example 'Jeeves_Smelly_Bum34' will become 'Jeeves_Smelly_Bum34(1)'
  •             *If a copy exists it will loop through until the numbers run out and creates the next file number.For example if 'Jeeves_Smelly_Bum34(1)' 'Jeeves_Smelly_Bum34(2)' 'Jeeves_Smelly_Bum34(3)' files exists in your directory then your file will be saved as 'Jeeves_Smelly_Bum34(1)'
  •             *Concatenates the directory(if present), new file name and file extension
  •             *Creates the file
  •             *Saves a copy of the file name for your use if needed. 


EXAMPLE 2 - File and Child Files You Want Saved With the Same File Name
       
import_new_file
chicken = new_file.new_file('blank.json','Jeeves #Smelly B^%#um34','JSON/', 'json')
duck = new_file.extra_file('none.png','Image/','png')
turkey = new_file.extra_file('Images/gobblegobble.jpg','','jpg')
emu = new_file.extra_file(''c:/Users/Batman/Documents/tmp.txt'','text/','txt')
       
         PROCESS

  •          *RUNS THROUGH STEPS IN FIRST EXAMPLE - as you can the 'chicken' instance runs through the new_file object. This is essentially the parent file. 
  •          * For 'duck','turkey' and 'emu' instances use the extra_file object and do the same thing as      each other.
  •          *GRABS NEW FILE NAME - Gets a copy of the new file name from the new_file object
  •          *IF IN DIRECTORY - Checks if file created in the new_file class is in a directory and removes 
  •          the directory if needed.
  •          *NEW DIRECTORY AND FILE - Concatenates the directory(if present), new file name and file extension

       
POSSIBLE USES
         REGISTER USER
         You could use the new_file module to save username data in a database file, save their avatar with the same name.
       
         GAME SAVE
         You need some control over the location of where the file needs to be saved here. You can use the users nickname as the name of the file and name any child files like avatar details file, game save location file, inventory file etc all with the same name.
       
P.S. I'm a noop hobbiest programmer. I created this module to help me with my first program. If you have any suggestions
for improvement I would appreciate any guidance. ~Scott

Hey you made it!


Friday 29 May 2015

Python - Finding an Item Between Two Characters In a String Using: partition and rpartition

I'm making a file saver at the moment and I need a little control over the location of the saved files so I can't use Python's handy tkFileDialog to save the file. This means I have to create my own file saver.

Problem

One of the problems my file saver might face is: what happens if a user chooses a file name that already exists. I'll have to rename the file.
So for example if the user creates a filename: batman.jpg. And a batman.jpg file already exists in the folder. Then I don't want to overwrite it. I want to give it the value: batman(1).jpg. Okay that is pretty easy to fix. Run a file search
But what if the user os.path.isfile search then and an if statement asking if the file exists. if it does:

All sorted.
But what if our user is the Hordor of Batman fans and wants to save every file as batman.jpg. We then I need a to run a for loop to search through the folder for batman(1)jpg, batman(2).jpg ... batman(x).jpg and then save it as the next number.

But how do I isolate the number?

Solution

Enter Pythons partition and rpartition. I need to get between the two brackets. I can use partition  split the string at the first bracket keeping everything after the occurrence. Then I can use rpartition to split the string at the last bracket keeping everything before the occurrence. Take a look at the example below:

Saturday 23 May 2015

Python 3 - Opening files Using the "with" Statement

I just learnt how to save a few lines when opening files in Python 3 using the with statement.

From what I understand, the statement uses try and then opens the file, processes it and closes it. How efficient is that?



To learn more about the with statement:
http://effbot.org/zone/python-with-statement.htm

Friday 22 May 2015

Python 3 - Install Modules and Packages Using PIP- Plus Troubleshooting

This is much of a quick reference for me than anything else.

PIP is the installer for modules and packages for Python. You can use it to install modules like mathplotlib and pygame. 
If you want a quick resource for python extension packages for your version of Python and your system then then:

Unofficial Windows Binaries for Python Extension Packages

is your one-stop-shop. 

To Download

Just:
  •  ctrl-f and type the item you want. 
  • Click the link. 
  • Select the version that matches your version of Python and 32 or 64 bit system.
  • Wait for it to down load. 
To Install
Once it has downloaded:
  • Go into your cmd for Windows (bash, iOS, terminal for Linux). In windows. Search for cmd, right click and run as administrator.
  • Once in, type: pip install package
    • For example:

  • Hi enter and it should install. 
  • To test if it works go into your Python terminal and type: import package
    • For example:

  • If there is no error then you have downloaded it successfully. If you get an error it may not have down loaded:


Troubleshooting in the CMD line

There are two issues I have come across that have caused me not to download the image in the command line:

'pip' is not recognized as an internal or external command,
operable program or batch file.

This is usually because you have two versions of pip installed on your computer (and more than likely you have installed Python 2.7 before Python 3.4)

To fix this problem you will need to type the whole path to your version of python you want to install your package on. In my case, I would type something like:

D:/Python34/Scripts/pip install package

Where the package is the name of the package, like mathplotlib. Your path may be in C:/ drive or in a different directory too. 

The second error will run the setup but will come up with:

warning: no files found matching 'distribute_setup.py'

And a big list of syntax errors.

For me, this is either as a result of a spelling mistake on by behalf or PIP could not find the file to install. To fix this I just accessed the directory and file where it was downloaded. 

For example:

pip install C:/Users/Scott/Downloads/package.v2iiBlahBlahBlah.whl

This seems to fix the problem. 



Wednesday 20 May 2015

Python 3 - Use In For In Range Loop To Do Differently Occurring Tasks

Problem

I wanted a fast way to run through an operation in a loop and then to do another operation, say every fifth time in Python 3.
You can run a loop in a certain range quite easily:

count = 1
for i in range (0,20):
print(count)
count += 1
This would reveal a list of numbers from 1 - 20 one under the other.
I knew that this was what I wanted to do but how could I print print ("ping") every fifth number (eg after,0,5,10,15,20)
My first direction was to use the step option in range which you can add to the end of your arguments:

count = 1
for i in range (0,20,5):
print(count)
count += 1
This would display:
1
2
3
4

The operation will loop through 20 times but every fifth time (step) the operation will print a number.
Not what I had in mind but useful.

Solution

The solution turned out to be fairly simple:

What I did was use two loops. One nested in the other. The first one printed the "ping". The nested loop counted through the numbers.
If I wanted the "ping" printed after every 5th time in a range of 20 it would occur 4 times (20/5 = 4). So I set the "ping" for loop for the to start at 0 and end at 4.
In the nested for loop I run the loop to 5 adding 1 to the count.
Now when the "ping" loop is run the first time it prints "ping" and counts from 1-5. The second time the "ping" loop runs it prints "ping" again and counts from 6-10.
This will continue until after the "ping" loop runs it's last loop at 4.

Applications

This might be useful for adding a note or a warning after a certain amount of data iterates through.
In a simple shooting game you might want to shoot a number of times before a rocket is launched if the fire key is still depressed. 

Monday 18 May 2015

Python 3 - Open File Dialog Window In Tkinter With filedialog

I wanted to make a file loader for a chatbot program I am working on in Python 3 using Tkinter. I thought  that it would be a tricky task until I stumbled up the filedialoge module and the askopenfilename function.

Tkinter uses the filedialoge access the askopenfilename to open a window that matches the format of your operating system. Mine is currently Windows 8, so it looks like this.


How good does that look. To use the askopenfilename function you need to import it:
from tkinter.filedialog import askopenfilename
Because you will probably want to run the file from a command in a menu bar of from a button click it's probably a good idea to wrap it in a function:
def OpenFile():
    name = askopenfilename(initialdir="C:/Users/Batman/tkinter/",
                           filetypes =(("Text File", "*.txt"),("All Files","*.*")),
                           title = "Choose a file."
                           )
The askopenfilename function can have a number of options or no options and you can leave it blank. The ones I have used in this example I think are the most useful:

initialdir 

 set the the initial file location that the function will open it.

filetypes


This allows you set the type of files you want the user open. The end result appears in the bottom drop down menu.
First you set the file in a tuple ("Text File", "*.txt"). The first input is the title you want to name the file type(e.g. "Text File") and the second string is the file name ("*.txt"). If you have a custom file type, like ("*.noob"), then you can use that too.
What I discovered is that it requires a minimum of two file types for this option to work. So if you get an error this might be it.

title

This is the title you want to add to the top bar. 


In the below example you can execute the file in the Menu in File-Open. I thought I'd give you a realistic application of the askopenfilename.
As you can see from the first print the file does not open the document, rather it gets the file location and from there you can open and use the file. In the above example I have opened the file as a variable and then read it because I had a text file. You could as easily put the variable in a label or text widget in tkinter.

Useful Links:
http://effbot.org/tkinterbook/tkinter-file-dialogs.htm
http://tkinter.unpythonic.net/wiki/tkFileDialog