Created
December 20, 2011 09:11
-
-
Save kpadmasola/1500900 to your computer and use it in GitHub Desktop.
IronPython program to download machine learning course videos to the specified download location. (see below to customize download location)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# IronPython program to download machine learning course videos to the specified download location. | |
# (see below to customize download location) | |
# | |
# Author: Krishna Padmasola | |
# Date: 20 Dec 2011 | |
import System; | |
import System.Net; | |
# change the value of downloadFolder as appropriate | |
downloadFolder = 'C:\\Temp\\' | |
# no need to touch anything below | |
serverUrl = 'http://download-videos.ml-class.org/cs229/videos/' | |
sections = [ | |
{ 'title': 'I. INTRODUCTION', 'videos': [ | |
{ 'title': 'Welcome (7 min)', 'file': '01.1-V3-Introduction-Welcome', 'id': '1', 'viewed': True }, | |
{ 'title': 'What is Machine Learning? (7 min)', 'file': '01.2-V2-Introduction-WhatIsMachineLearning', 'id': '2', 'viewed': True }, | |
{ 'title': 'Supervised Learning (12 min)', 'file': '01.3-V2-Introduction-SupervisedLearning', 'id': '3', 'viewed': True }, | |
{ 'title': 'Unsupervised Learning (14 min)', 'file': '01.4-V2-Introduction-UnsupervisedLearning', 'id': '4', 'viewed': True } | |
]}, | |
{ 'title': 'II. LINEAR REGRESSION WITH ONE VARIABLE', 'videos': [ | |
{ 'title': 'Model Representation (8 min)', 'file': '02.1-V2-LinearRegressionWithOneVariable-ModelRepresentation', 'id': '5', 'viewed': True }, | |
{ 'title': 'Cost Function (8 min)', 'file': '02.2-V2-LinearRegressionWithOneVariable-CostFunction', 'id': '6', 'viewed': True }, | |
{ 'title': 'Cost Function - Intuition I (11 min)', 'file': '02.3-V2-LinearRegressionWithOneVariable-CostFunctionIntuitionI', 'id': '7', 'viewed': True }, | |
{ 'title': 'Cost Function - Intuition II (9 min)', 'file': '02.4-V2-LinearRegressionWithOneVariable-CostFunctionIntuitionII', 'id': '8', 'viewed': True }, | |
{ 'title': 'Gradient Descent (11 min)', 'file': '02.5-V2-LinearRegressionWithOneVariable-GradientDescent', 'id': '9', 'viewed': True }, | |
{ 'title': 'Gradient Descent Intuition (12 min)', 'file': '02.6-V2-LinearRegressionWithOneVariable-GradientDescentIntuition', 'id': '10', 'viewed': True }, | |
{ 'title': 'Gradient Descent For Linear Regression (10 min)', 'file': '02.7-V2-LinearRegressionWithOneVariable-GradientDescentForLinearRegression', 'id': '11', 'viewed': True }, | |
{ 'title': 'What\'s Next (6 min)', 'file': '02.8-V2-What\'sNext', 'id': '12', 'viewed': True } | |
]}, | |
{ 'title': 'III. LINEAR ALGEBRA REVIEW (OPTIONAL)', 'videos': [ | |
{ 'title': 'Matrices and Vectors (9 min)', 'file': '03.1-V2-LinearAlgebraReview(Optional)-MatricesAndVectors', 'id': '13', 'viewed': True }, | |
{ 'title': 'Addition and Scalar Multiplication (7 min)', 'file': '03.2-V2-LinearAlgebraReview(Optional)-AdditionAndScalarMultiplication', 'id': '14', 'viewed': True }, | |
{ 'title': 'Matrix Vector Multiplication (14 min)', 'file': '03.3-V2-LinearAlgebraReview(Optional)-MatrixVectorMultiplication', 'id': '15', 'viewed': False }, | |
{ 'title': 'Matrix Matrix Multiplication (11 min)', 'file': '03.4-V2-LinearAlgebraReview(Optional)-MatrixMatrixMultiplication', 'id': '16', 'viewed': False }, | |
{ 'title': 'Matrix Multiplication Properties (9 min)', 'file': '03.5-V2-LinearAlgebraReview(Optional)-MatrixMultiplicationProperties', 'id': '17', 'viewed': False }, | |
{ 'title': 'Inverse and Transpose (11 min)', 'file': '03.6-V2-LinearAlgebraReview(Optional)-InverseAndTranspose', 'id': '18', 'viewed': True } | |
]}, | |
{ 'title': 'IV. LINEAR REGRESSION WITH MULTIPLE VARIABLES', 'videos': [ | |
{ 'title': 'Multiple Features (8 min)', 'file': '04.1-LinearRegressionWithMultipleVariables-MultipleFeatures', 'id': '19', 'viewed': True }, | |
{ 'title': 'Gradient Descent for Multiple Variables (6 min)', 'file': '04.2-LinearRegressionWithMultipleVariables-GradientDescentForMultipleVariables', 'id': '20', 'viewed': True }, | |
{ 'title': 'Gradient Descent in Practice I - Feature Scaling (9 min)', 'file': '04.3-LinearRegressionWithMultipleVariables-GradientDescentInPracticeIFeatureScaling', 'id': '21', 'viewed': True }, | |
{ 'title': 'Gradient Descent in Practice II - Learning Rate (9 min)', 'file': '04.4-LinearRegressionWithMultipleVariables-GradientDescentInPracticeIILearningRate', 'id': '22', 'viewed': True }, | |
{ 'title': 'Features and Polynomial Regression (8 min)', 'file': '04.5-LinearRegressionWithMultipleVariables-FeaturesAndPolynomialRegression', 'id': '23', 'viewed': True }, | |
{ 'title': 'Normal Equation (16 min)', 'file': '04.6-V2-LinearRegressionWithMultipleVariables-NormalEquation', 'id': '24', 'viewed': True }, | |
{ 'title': 'Normal Equation Noninvertibility (Optional) (6 min)', 'file': '04.7-LinearRegressionWithMultipleVariables-NormalEquationNonInvertibility(Optional)', 'id': '25', 'viewed': True } | |
]}, | |
{ 'title': 'V. OCTAVE TUTORIAL', 'videos': [ | |
{ 'title': 'Basic Operations (14 min)', 'file': '05.1-OctaveTutorial-BasicOperations', 'id': '26', 'viewed': True }, | |
{ 'title': 'Moving Data Around (16 min)', 'file': '05.2-OctaveTutorial-MovingDataAround', 'id': '27', 'viewed': True }, | |
{ 'title': 'Computing on Data (13 min)', 'file': '05.3-OctaveTutorial-ComputingOnData', 'id': '28', 'viewed': True }, | |
{ 'title': 'Plotting Data (10 min)', 'file': '05.4-OctaveTutorial-PlottingData', 'id': '29', 'viewed': True }, | |
{ 'title': 'Control Statements: for, while, if statements (13 min)', 'file': '05.5-OctaveTutorial-ForWhileIfStatementsAndFunctions', 'id': '30', 'viewed': True }, | |
{ 'title': 'Vectorization (14 min)', 'file': '05.6-OctaveTutorial-Vectorization', 'id': '31', 'viewed': True }, | |
{ 'title': 'Working on and Submitting Programming Exercises (4 min)', 'file': '05.7-OctaveTutorial-WorkingOnAndSubmittingProgrammingExercises', 'id': '32', 'viewed': True } | |
]}, | |
{ 'title': 'VI. LOGISTIC REGRESSION', 'videos': [ | |
{ 'title': 'Classification (8 min)', 'file': '06.1-LogisticRegression-Classification', 'id': '33', 'viewed': True }, | |
{ 'title': 'Hypothesis Representation (7 min)', 'file': '06.2-LogisticRegression-HypothesisRepresentation', 'id': '34', 'viewed': True }, | |
{ 'title': 'Decision Boundary (15 min)', 'file': '06.3-LogisticRegression-DecisionBoundary', 'id': '35', 'viewed': True }, | |
{ 'title': 'Cost Function (11 min)', 'file': '06.4-LogisticRegression-CostFunction', 'id': '36', 'viewed': True }, | |
{ 'title': 'Simplified Cost Function and Gradient Descent (10 min)', 'file': '06.5-LogisticRegression-SimplifiedCostFunctionAndGradientDescent', 'id': '37', 'viewed': True }, | |
{ 'title': 'Advanced Optimization (14 min)', 'file': '06.6-LogisticRegression-AdvancedOptimization', 'id': '38', 'viewed': True }, | |
{ 'title': 'Multiclass Classification: One-vs-all (6 min)', 'file': '06.7-LogisticRegression-MultiClassClassificationOneVsAll', 'id': '39', 'viewed': True } | |
]}, | |
{ 'title': 'VII. REGULARIZATION', 'videos': [ | |
{ 'title': 'The Problem of Overfitting', 'file': '07.1-Regularization-TheProblemOfOverfitting', 'id': '41', 'viewed': True }, | |
{ 'title': 'Cost Function (10 min)', 'file': '07.2-Regularization-CostFunction', 'id': '42', 'viewed': True }, | |
{ 'title': 'Regularized Linear Regression (11 min)', 'file': '07.3-Regularization-RegularizedLinearRegression', 'id': '43', 'viewed': True }, | |
{ 'title': 'Regularized Logistic Regression (9 min)', 'file': '07.4-Regularization-RegularizedLogisticRegression', 'id': '44', 'viewed': True } | |
]}, | |
{ 'title': 'VIII. NEURAL NETWORKS: REPRESENTATION', 'videos': [ | |
{ 'title': 'Non-linear Hypotheses (10 min)', 'file': '08.1-NeuralNetworksRepresentation-NonLinearHypotheses', 'id': '45', 'viewed': True }, | |
{ 'title': 'Neurons and the Brain (8 min)', 'file': '08.2-NeuralNetworksRepresentation-NeuronsAndTheBrain', 'id': '46', 'viewed': True }, | |
{ 'title': 'Model Representation I (12 min)', 'file': '08.3-NeuralNetworksRepresentation-ModelRepresentationI', 'id': '47', 'viewed': True }, | |
{ 'title': 'Model Representation II (12 min)', 'file': '08.4-NeuralNetworksRepresentation-ModelRepresentationII', 'id': '48', 'viewed': True }, | |
{ 'title': 'Examples and Intuitions I (7 min)', 'file': '08.5-NeuralNetworksRepresentation-ExamplesAndIntuitionsI', 'id': '49', 'viewed': True }, | |
{ 'title': 'Examples and Intuitions II (10 min)', 'file': '08.6-NeuralNetworksRepresentation-ExamplesAndIntuitionsII', 'id': '50', 'viewed': True }, | |
{ 'title': 'Multiclass Classification (4 min)', 'file': '08.7-NeuralNetworksRepresentation-MultiClassClassification', 'id': '51', 'viewed': True } | |
]}, | |
{ 'title': 'IX. NEURAL NETWORKS: LEARNING', 'videos': [ | |
{ 'title': 'Cost Function (7 min)', 'file': '09.1-NeuralNetworksLearning-CostFunction', 'id': '52', 'viewed': True }, | |
{ 'title': 'Backpropagation Algorithm (12 min)', 'file': '09.2-NeuralNetworksLearning-BackpropagationAlgorithm', 'id': '53', 'viewed': True }, | |
{ 'title': 'Backpropagation Intuition (13 min)', 'file': '09.3-NeuralNetworksLearning-BackpropagationIntuition', 'id': '57', 'viewed': True }, | |
{ 'title': 'Implementation Note: Unrolling Parameters (8 min)', 'file': '09.3-NeuralNetworksLearning-ImplementationNoteUnrollingParameters', 'id': '54', 'viewed': True }, | |
{ 'title': 'Gradient Checking (8 min)', 'file': '09.4-NeuralNetworksLearning-GradientChecking', 'id': '55', 'viewed': True }, | |
{ 'title': 'Random Initialization (7 min)', 'file': '09.5-NeuralNetworksLearning-RandomInitialization', 'id': '56', 'viewed': True }, | |
{ 'title': 'Putting It Together (14 min)', 'file': '09.7-NeuralNetworksLearning-PuttingItTogether', 'id': '58', 'viewed': True }, | |
{ 'title': 'Autonomous Driving (7 min)', 'file': '09.8-NeuralNetworksLearning-AutonomousDrivingExample', 'id': '59', 'viewed': True } | |
]}, | |
{ 'title': 'X. ADVICE FOR APPLYING MACHINE LEARNING', 'videos': [ | |
{ 'title': 'Deciding What to Try Next (6 min)', 'file': '10.1-AdviceForApplyingMachineLearning-DecidingWhatToTryNext', 'id': '60', 'viewed': True }, | |
{ 'title': 'Evaluating a Hypothesis (8 min)', 'file': '10.2-AdviceForApplyingMachineLearning-EvaluatingAHypothesis', 'id': '61', 'viewed': True }, | |
{ 'title': 'Model Selection and Train Validation Test Sets (13 min)', 'file': '10.3-AdviceForApplyingMachineLearning-ModelSelectionAndTrainValidationTestSets', 'id': '62', 'viewed': True }, | |
{ 'title': 'Diagnosing Bias vs. Variance (9 min)', 'file': '10.4-AdviceForApplyingMachineLearning-DiagnosingBiasVsVariance', 'id': '63', 'viewed': True }, | |
{ 'title': 'Regularization and Bias Variance (12 min)', 'file': '10.5-AdviceForApplyingMachineLearning-RegularizationAndBiasVariance', 'id': '64', 'viewed': True }, | |
{ 'title': 'Learning Curves (12 min)', 'file': '10.6-AdviceForApplyingMachineLearning-LearningCurves', 'id': '65', 'viewed': True }, | |
{ 'title': 'Deciding What to Do Next Revisited (7 min)', 'file': '10.7-AdviceForApplyingMachineLearning-DecidingWhatToDoNextRevisited', 'id': '66', 'viewed': True } | |
]}, | |
{ 'title': 'XI. MACHINE LEARNING SYSTEM DESIGN', 'videos': [ | |
{ 'title': 'Prioritzing What to Work On (10 min)', 'file': '11.1-MachineLearningSystemDesign-PrioritizingWhatToWorkOn', 'id': '67', 'viewed': True }, | |
{ 'title': 'Error Analysis (13 min)', 'file': '11.2-MachineLearningSystemDesign-ErrorAnalysis', 'id': '68', 'viewed': True }, | |
{ 'title': 'Error Metrics for Skewed Classes (12 min)', 'file': '11.3-MachineLearningSystemDesign-ErrorMetricsForSkewedClasses', 'id': '69', 'viewed': True }, | |
{ 'title': 'Trading Off Precision and Recall (14 min)', 'file': '11.4-MachineLearningSystemDesign-TradingOffPrecisionAndRecall', 'id': '70', 'viewed': True }, | |
{ 'title': 'Data For Machine Learning (11 min)', 'file': '11.5-MachineLearningSystemDesign-DataForMachineLearning', 'id': '71', 'viewed': True } | |
]}, | |
{ 'title': 'XII. SUPPORT VECTOR MACHINES', 'videos': [ | |
{ 'title': 'Optimization Objective (15 min)', 'file': '12.1-SupportVectorMachines-OptimizationObjective', 'id': '72', 'viewed': True }, | |
{ 'title': 'Large Margin Intuition (11 min)', 'file': '12.2-SupportVectorMachines-LargeMarginIntuition', 'id': '73', 'viewed': True }, | |
{ 'title': 'Mathematics Behind Large Margin Classification (Optional) (20 min)', 'file': '12.3-SupportVectorMachines-MathematicsBehindLargeMarginClassificationOptional', 'id': '74', 'viewed': True }, | |
{ 'title': 'Kernels I (16 min)', 'file': '12.4-SupportVectorMachines-KernelsI', 'id': '75', 'viewed': True }, | |
{ 'title': 'Kernels II (16 min)', 'file': '12.5-SupportVectorMachines-KernelsII', 'id': '76', 'viewed': True }, | |
{ 'title': 'Using An SVM (21 min)', 'file': '12.6-SupportVectorMachines-UsingAnSVM', 'id': '77', 'viewed': True } | |
]}, | |
{ 'title': 'XIII. CLUSTERING', 'videos': [ | |
{ 'title': 'Unsupervised Learning: Introduction (3 min)', 'file': '14.1-Clustering-UnsupervisedLearningIntroduction', 'id': '78', 'viewed': True }, | |
{ 'title': 'K-Means Algorithm (13 min)', 'file': '14.2-Clustering-KMeansAlgorithm', 'id': '79', 'viewed': True }, | |
{ 'title': 'Optimization Objective (7 min)', 'file': '14.3-Clustering-OptimizationObjective', 'id': '80', 'viewed': True }, | |
{ 'title': 'Random Initialization (7 min)', 'file': '14.4-Clustering-RandomInitialization', 'id': '81', 'viewed': True }, | |
{ 'title': 'Choosing the Number of Clusters (9 min)', 'file': '14.5-Clustering-ChoosingTheNumberOfClusters', 'id': '82', 'viewed': True } | |
]}, | |
{ 'title': 'XIV. DIMENSIONALITY REDUCTION', 'videos': [ | |
{ 'title': 'Motivation I: Data Compression (10 min)', 'file': '15.1-DimensionalityReduction-MotivationIDataCompression', 'id': '83', 'viewed': True }, | |
{ 'title': 'Motivation II: Visualization (6 min)', 'file': '15.2-DimensionalityReduction-MotivationIIVisualization', 'id': '84', 'viewed': True }, | |
{ 'title': 'Principal Component Analysis Problem Formulation (9 min)', 'file': '15.3-DimensionalityReduction-PrincipalComponentAnalysisProblemFormulation', 'id': '85', 'viewed': True }, | |
{ 'title': 'Principal Component Analysis Algorithm (15 min)', 'file': '15.4-DimensionalityReduction-PrincipalComponentAnalysisAlgorithm', 'id': '86', 'viewed': True }, | |
{ 'title': 'Choosing the Number of Principal Components (11 min)', 'file': '15.5-DimensionalityReduction-ChoosingTheNumberOfPrincipalComponents', 'id': '87', 'viewed': True }, | |
{ 'title': 'Reconstruction from Compressed Representation (4 min)', 'file': '15.6-DimensionalityReduction-ReconstructionFromCompressedRepresentation', 'id': '89', 'viewed': True }, | |
{ 'title': 'Advice for Applying PCA (13 min)', 'file': '15.7-DimensionalityReduction-AdviceForApplyingPCA', 'id': '90', 'viewed': True } | |
]}, | |
{ 'title': 'XV. ANOMALY DETECTION', 'videos': [ | |
{ 'title': 'Problem Motivation (8 min)', 'file': '16.1-AnomalyDetection-ProblemMotivation-V1', 'id': '91', 'viewed': True }, | |
{ 'title': 'Gaussian Distribution (8 min)', 'file': '16.2-AnomalyDetection-GaussianDistribution', 'id': '92', 'viewed': True }, | |
{ 'title': 'Algorithm (12 min)', 'file': '16.3-AnomalyDetection-Algorithm', 'id': '94', 'viewed': True }, | |
{ 'title': 'Developing and Evaluating an Anomaly Detection System (13 min)', 'file': '16.4-AnomalyDetection-DevelopingAndEvaluatingAnAnomalyDetectionSystem', 'id': '93', 'viewed': True }, | |
{ 'title': 'Anomaly Detection vs. Supervised Learning (8 min)', 'file': '16.5-AnomalyDetection-AnomalyDetectionVsSupervisedLearning-V1', 'id': '95', 'viewed': True }, | |
{ 'title': 'Choosing What Features to Use (12 min)', 'file': '16.6-AnomalyDetection-ChoosingWhatFeaturesToUse', 'id': '96', 'viewed': True }, | |
{ 'title': 'Multivariate Gaussian Distribution (Optional) (14 min)', 'file': '16.7-AnomalyDetection-MultivariateGaussianDistribution-OPTIONAL', 'id': '97', 'viewed': True }, | |
{ 'title': 'Anomaly Detection using the Multivariate Gaussian Distribution (Optional) (14 min)', 'file': '16.8-AnomalyDetection-AnomalyDetectionUsingTheMultivariateGaussianDistribution-OPTIONAL', 'id': '98', 'viewed': True } | |
]}, | |
{ 'title': 'XVI. RECOMMENDER SYSTEMS', 'videos': [ | |
{ 'title': 'Problem Formulation (8 min)', 'file': '17.1-RecommenderSystems-ProblemFormulation', 'id': '99', 'viewed': True }, | |
{ 'title': 'Content Based Recommendations (15 min)', 'file': '17.2-RecommenderSystems-ContentBasedRecommendations', 'id': '100', 'viewed': True }, | |
{ 'title': 'Collaborative Filtering (10 min)', 'file': '17.3-RecommenderSystems-CollaborativeFiltering-V1', 'id': '101', 'viewed': True }, | |
{ 'title': 'Collaborative Filtering Algorithm (9 min)', 'file': '17.4-RecommenderSystems-CollaborativeFilteringAlgorithm', 'id': '102', 'viewed': True }, | |
{ 'title': 'Vectorization: Low Rank Matrix Factorization (8 min)', 'file': '17.5-RecommenderSystems-VectorizationLowRankMatrixFactorization', 'id': '103', 'viewed': True }, | |
{ 'title': 'Implementational Detail: Mean Normalization (9 min)', 'file': '17.6-RecommenderSystems-ImplementationalDetailMeanNormalization', 'id': '104', 'viewed': True } | |
]}, | |
{ 'title': 'XVII. LARGE SCALE MACHINE LEARNING', 'videos': [ | |
{ 'title': 'Learning With Large Datasets (6 min)', 'file': '18.1-LargeScaleMachineLearning-LearningWithLargeDatasets', 'id': '105', 'viewed': True }, | |
{ 'title': 'Stochastic Gradient Descent (13 min)', 'file': '18.2-LargeScaleMachineLearning-StochasticGradientDescent', 'id': '106', 'viewed': True }, | |
{ 'title': 'Mini-Batch Gradient Descent (6 min)', 'file': '18.3-LargeScaleMachineLearning-MiniBatchGradientDescent', 'id': '107', 'viewed': True }, | |
{ 'title': 'Stochastic Gradient Descent Convergence (12 min)', 'file': '18.4-LargeScaleMachineLearning-StochasticGradientDescentConvergence', 'id': '108', 'viewed': True }, | |
{ 'title': 'Online Learning (13 min)', 'file': '18.5-LargeScaleMachineLearning-OnlineLearning', 'id': '109', 'viewed': True }, | |
{ 'title': 'Map Reduce and Data Parallelism (15 min)', 'file': '18.6-LargeScaleMachineLearning-MapReduceAndDataParallelism', 'id': '110', 'viewed': True } | |
]}, | |
{ 'title': 'XVIII. APPLICATION EXAMPLE: PHOTO OCR', 'videos': [ | |
{ 'title': 'Problem Description and Pipeline (7 min)', 'file': '19.1-ApplicationExamplePhotoOCR-ProblemDescriptionAndPipeline', 'id': '111', 'viewed': True }, | |
{ 'title': 'Sliding Windows (15 min)', 'file': '19.2-ApplicationExamplePhotoOCR-SlidingWindows', 'id': '112', 'viewed': True }, | |
{ 'title': 'Getting Lots of Data and Artificial Data (14 min)', 'file': '19.3-ApplicationExamplePhotoOCR-GettingLotsOfDataArtificialDataSynthesis', 'id': '113', 'viewed': True }, | |
{ 'title': 'Ceiling Analysis: What Part of the Pipeline to Work on Next (14 min)', 'file': '19.4-ApplicationExamplePhotoOCR-CeilingAnalysisWhatPartOfThePipelineToWorkOnNext', 'id': '114', 'viewed': False } | |
]}, | |
{ 'title': 'XIX. CONCLUSION', 'videos': [ | |
{ 'title': 'Summary and Thank You (5 min)', 'file': '20.1-Conclusion-SummaryAndThankYou', 'id': '115', 'viewed': True } | |
]}]; | |
if __name__=='__main__': | |
webclient = System.Net.WebClient() | |
for section in sections: | |
for video in section['videos']: | |
filename = video['file'] + '.mp4' | |
destinationFileName = downloadFolder + filename | |
sourceFileName = serverUrl + filename | |
print 'Downloading ' + sourceFileName + '...' | |
webclient.DownloadFile(sourceFileName, destinationFileName) | |
print 'Done!' | |
print 'All downloads completed!' | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This IronPython script downloads the lecture videos from Prof. Andrew Ng's Machine Learning class of Fall 2011 (http://ml-class.org). Basically I massaged the source of http://www.ml-class.org/course/video/list?mode=download a wee bit to convert JSON data structures into python data structures, and the rest was straightforward. You should be able to convert it regular Python script fairly easily, if required. I used IronPython as I have a Windows laptop and Visual Studio has a great IDE for editing Python scripts (http://pytools.codeplex.com/). Let me know if you find this script useful. Enjoy :)