Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
QuarkJets
Sep 8, 2008

Opinion Haver posted:

Yeah, but you could still do this:

code:
if x.nonefind('eggs') is not None: print('found it!')

But that's pointless because you have the 'in' operator and could just do an integer comparison even if you didn't

Adbot
ADBOT LOVES YOU

Dren
Jan 5, 2001

Pillbug

Pollyanna posted:

Has anyone here done Shift-JIS decoding/encoding? I have a .bin file encoded with Shift-JIS (Japanese text), and I want to read each byte and translate them to UTF-8 or UTF-16. What I was thinking of was looping through it with file.read(1), then decoding/encoding the selected bytes (if that makes any sense). Would this work? Cause so far I just get strings like '/x00/xac' and I don't know how to change that to readable text. Has this been done before? Should I be reading one or two bytes at a time? What final encoding should I use? How I do :saddowns:

iconv

SurgicalOntologist
Jun 17, 2004

Are there agreements on error message conventions? Specifically I'm wondering if it's better to say what the program requires or what went wrong.

For example, which is better:
The sort method 'ordered' requires the parent section to contain an independent variable 'ascending' or 'descending'
or
No independent variable 'ascending' or 'descending' in parent section

I suppose the second type is closer to the built-in exception messages. Thoughts? I guess I'd want to include all the information though:
No independent variable 'ascending' or 'descending' in parent of section with sort method 'ordered'

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
No error message shown to a user should be that incomprehensible.

SurgicalOntologist
Jun 17, 2004

I probably should've came up with a more generic example to ask my question.

But I do think my users will understand. It's a fairly niche userbase. It's a library for designing psychology experiments. An experiment is set up as a hierarchy of sections, e.g. an experiment contains sessions, sessions contain blocks, blocks contain trials. When you create your experiment you specify how you want a sort method for each section as one of {'random', 'complete-counterbalance', 'latin-square', 'ordered'}. The users understand these terms but nevertheless they will be explained in the documentation.

Users also specify independent variables, each associated with a section. This is also a completely commonplace term for experimentalists. For example, if an IV at the trial level is "luminance" your experiment might vary the luminance level of some stimulus every trial. Every IV needs a set of values it can take as well.

The use case for the 'ordered' sort method is that you're interested in comparing what happens when you present the trials in ascending vs. descending order. For example, does the point at which you can detect the stimulus as luminance increases differ from the point at which you can no longer detect the stimulus as luminance decreases (hysteresis)? In this kind of experiment the IV of interest is order. You'll want to have some blocks order trials by increasing luminance, and some by decreasing luminance.

Anyone using this feature knows all this, and if they don't set order as an IV with possible values of 'ascending' and 'descending' they probably made a mistake organizing their experiment.


Anyways, I don't know why I bothered to explain all that, my question still stands. Is it better for an error message to state the condition that wasn't met, or to state the faulty condition that occurred? Function F cannot handle inputs of type X or Input to function F must of type Y? Of course as soon as I posted my question I realized that you would ideally fit both types of information in there. Still, if there was some common convention written somewhere it would be nice to see. (It's one of those times when I thought to myself, maybe if I hadn't been self-taught I would have learned guidelines for this case. So I thought I'd ask.)

Dren
Jan 5, 2001

Pillbug
It would be better for you to write terse error messages good enough to allow the user to figure out where to look in the excellent documentation you provide for your API.

BeefofAges
Jun 5, 2004

Cry 'Havoc!', and let slip the cows of war.

Should I go to PyCon? My department gets to send a few people, but I feel like I should let some of the less experienced developers go in my place. I was looking over the schedule and I didn't really see any talks I feel excited about. Then again, I've never actually been.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

SurgicalOntologist posted:

It's a library for designing psychology experiments.

Unless your error messages are the psychology experiment, you shouldn't have "Invalid input X to function Y" messages.

Think about what error messages you'd display to the user if this was a web app or a desktop app: there are no functions here at all! Designing an experiment in these applications is not expressed in terms of functions.

Your library sounds like it's a "UI" of sorts in the same vein. The same sort of care should be taken with your messages as well.

I don't know much about this library or the experiments within, but how about "Data is sorted with 'random', but IV order set as 'ascending'" ? In a real UI, of course, you'd simply grey out the combobox or whatever to prevent the user from choosing the invalid combination in the first place.

Opinion Haver
Apr 9, 2007

QuarkJets posted:

But that's pointless because you have the 'in' operator and could just do an integer comparison even if you didn't

I mean, having separate boolean and integer types is also 'pointless' because you can just use 1 for true and 0 for false. Just because C's strstr has to return -1 doesn't mean that has to be carried forward into other languages.

SurgicalOntologist
Jun 17, 2004

Suspicious Dish posted:

Unless your error messages are the psychology experiment, you shouldn't have "Invalid input X to function Y" messages.

Think about what error messages you'd display to the user if this was a web app or a desktop app: there are no functions here at all! Designing an experiment in these applications is not expressed in terms of functions.

Your library sounds like it's a "UI" of sorts in the same vein. The same sort of care should be taken with your messages as well.

I don't know much about this library or the experiments within, but how about "Data is sorted with 'random', but IV order set as 'ascending'" ? In a real UI, of course, you'd simply grey out the combobox or whatever to prevent the user from choosing the invalid combination in the first place.

Right, the "input X to function Y" message was a generic example I pulled out of my rear end and has nothing to do with my project.

Anyways this project is not UI at all, it's a library, my users are writing code when they make experiments. The idea of the library is to eliminate the boilerplate that gets written around the actual unique code of an experiment. Basically it takes a user-defined "run_trial" function and calls it a specific number of times over a number of Python sessions while systematically varying the inputs and collecting the results in a friendly data structure. All based on principles of experimental design.

(Oh, if you got the UI idea from some of my other recent questions, the thing about hardware sensors and callbacks is for a different project--though ultimately these two projects together will power a number of experiments my lab has in the pipeline)

That error message suggestion doesn't really capture the problem in this case but it is a helpful example, thanks.

(And sorry if I've been making GBS threads up the thread with my newbie-over-his-head questions. This forum has been a great resource over the past few months; I'm desperately trying to put together a software repertoire before I finish my Ph.D. and inevitably fail to get an academic research job. While also trying to get research done along the way.)

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
You should always be thinking about the design of the library, of your APIs, and how the user will interface with it.

Just because it's code, doesn't mean it's not something that needs to be designed.

SurgicalOntologist posted:

Right, the "input X to function Y" message was a generic example I pulled out of my rear end and has nothing to do with my project.

This bugs me to no end. You asked if this error message, phrased like "input X to function Y", was a good one. That was the entire question you asked in the first post. If it's unrelated and you pulled it out of your rear end, why did you ask it and expect us to answer it?

QuarkJets
Sep 8, 2008

Opinion Haver posted:

I mean, having separate boolean and integer types is also 'pointless' because you can just use 1 for true and 0 for false. Just because C's strstr has to return -1 doesn't mean that has to be carried forward into other languages.

It's not carried over, use the 'in' operator. Stop using find for testing whether a substring exists

QuarkJets
Sep 8, 2008

SurgicalOntologist posted:

Right, the "input X to function Y" message was a generic example I pulled out of my rear end and has nothing to do with my project.

Anyways this project is not UI at all, it's a library, my users are writing code when they make experiments. The idea of the library is to eliminate the boilerplate that gets written around the actual unique code of an experiment. Basically it takes a user-defined "run_trial" function and calls it a specific number of times over a number of Python sessions while systematically varying the inputs and collecting the results in a friendly data structure. All based on principles of experimental design.

(Oh, if you got the UI idea from some of my other recent questions, the thing about hardware sensors and callbacks is for a different project--though ultimately these two projects together will power a number of experiments my lab has in the pipeline)

That error message suggestion doesn't really capture the problem in this case but it is a helpful example, thanks.

(And sorry if I've been making GBS threads up the thread with my newbie-over-his-head questions. This forum has been a great resource over the past few months; I'm desperately trying to put together a software repertoire before I finish my Ph.D. and inevitably fail to get an academic research job. While also trying to get research done along the way.)

If your user is writing their own functions and then providing invalid input to them, then you shouldn't be trying to predict that. It's their own fault for doing A Dumb Thing. I still don't really understand what you're trying to do, there was a lot of psychology lingo that didn't really help to illustrate the problem at all. Let me see if I understand correctly:

1) The user creates a bunch of sections, each with an independent variable

2) The user writes a function that uses these variables in some way and returns a result

3) You loop over the variables, iterate them in a user-chosen way (randomly, or ordered, or whatever), and then you store all of the results in a big data structure that you return to the user

So basically you want to be able to tell the user some of the time that their initialized variables are wrong, or something?

e: Now that we've established what the actual question isn't, how about telling us what the actual question is? I think that there are a lot of people really interested in helping you, but I'd like more details on the circumstances of your question. If you're worried about users providing invalid input to the functions that they wrote, don't be; it's their responsibility to write functions that take the inputs that they're going to provide. If you're worried about users providing invalid input to the functions that you wrote, then throw an Exception that very briefly says what the issue is. For instance, if the user says to iterate from 0-10 and then says to initialize that variable to 50, you could raise an exception that says something like "Initialization outside of iteration range"

If this software is going to be used in big experiments, then it'd probably be best to even pre-check the inputs for validity and just immediately raise an exception that points to a piece of input and very briefly describes the issue.

SurgicalOntologist
Jun 17, 2004

Suspicious Dish posted:

You should always be thinking about the design of the library, of your APIs, and how the user will interface with it.

Just because it's code, doesn't mean it's not something that needs to be designed.

Yeah, the API has always been the focal point, and what I most enjoyed designing. I didn't mean to suggest that it's not important or doesn't need to be designed. I think it's quite elegant actually (although I wouldn't be surprised if someone tells me it's not). Here's what an example would look like:
Python code:
from experimentator import Experiment, run_experiment_section

my_experiment = Exeriment(config_file='config.ini',
                          experiment_file='my_experiment.dat')


@my_experiment.run
def run_trial(**kwargs):
   # Do stuff based on the IVs in kwargs
    return trial_result


@my_experiment.start('session')
def initialize_display(**_):
    # Code goes here


@my_experiment.inter('block')
def offer_break(**_):
    # Offer the participant to take a break in-between blocks


@my_experiment.end('session')
def close_display(**_):
    # You get the idea


# Then, in another python session:
run_experiment_section('my_experiment.dat', participant=1, session=1)
To be fair, it gets kind of hairy if the user chooses not to use a config file to define the structure of the experiment, but I did the best I could.

Suspicious Dish posted:

This bugs me to no end. You asked if this error message, phrased like "input X to function Y", was a good one. That was the entire question you asked in the first post. If it's unrelated and you pulled it out of your rear end, why did you ask it and expect us to answer it?

Actually, that was in the second post, in the first post I used the actual example from my project. Then I found myself having to explain the whole project just to ask a generic question (I was more interested in the principle of "what went wrong" vs. "what is required" than what would be an ideal error message for my situation) so in the second post, after explaining everything, I put that in, so that if the explanation of my entire project wasn't clear, maybe the question would still get across.

Dren
Jan 5, 2001

Pillbug
If you are providing a library take a look at sphinx and try to write code with docstrings that generate nice sphinx docs.

It seems like you're trying really hard to generate meaningful error messages that provide a lot of help for the user. You should have clear error messages but save the more serious explanations for the documentation.

SurgicalOntologist
Jun 17, 2004

QuarkJets posted:

If your user is writing their own functions and then providing invalid input to them, then you shouldn't be trying to predict that. It's their own fault for doing A Dumb Thing. I still don't really understand what you're trying to do, there was a lot of psychology lingo that didn't really help to illustrate the problem at all. Let me see if I understand correctly:

1) The user creates a bunch of sections, each with an independent variable

2) The user writes a function that uses these variables in some way and returns a result

3) You loop over the variables, iterate them in a user-chosen way (randomly, or ordered, or whatever), and then you store all of the results in a big data structure that you return to the user

So basically you want to be able to tell the user some of the time that their initialized variables are wrong, or something?

That explanation is pretty close, though the actual structure is more complicated and closer to a tree: For example, an experiment contains 20 participants. Participants each contain two sessions, each session contains four blocks, each block contains 50 trials. Participant sections know how to order and run sessions, sessions know how to order and run blocks, etc.

The error arises because some of the ordering methods are atomic (e.g., if you're ordering trials randomly within a block each block can do it's own thing) but others aren't. If you're ordering trials in an incremental (sorted) order, you might want some blocks to order trials ascending and some descending. Ascending and descending are now functioning as IVs at the block level because now you might want to control how the blocks are themselves ordered. Alternate descending and ascending blocks, or perhaps do all the ascending blocks first and then all the descending blocks. Put another way, how one section orders its children can depend on an IV managed by the level above. I wanted to raise an error if that IV doesn't exist because probably something went wrong. Alternatively I could do ascending by default but I think that might let mistakes slip through.

QuarkJets posted:

e: Now that we've established what the actual question isn't, how about telling us what the actual question is? I think that there are a lot of people really interested in helping you, but I'd like more details on the circumstances of your question. If you're worried about users providing invalid input to the functions that they wrote, don't be; it's their responsibility to write functions that take the inputs that they're going to provide. If you're worried about users providing invalid input to the functions that you wrote, then throw an Exception that very briefly says what the issue is. For instance, if the user says to iterate from 0-10 and then says to initialize that variable to 50, you could raise an exception that says something like "Initialization outside of iteration range"

Hopefully that's enough details, but your example at the end of the paragraph here is illuminating. The alternative to "Initialization outside of iteration range" that also seems reasonable to me is "Initialization must be within 0-10". The former says what went wrong, the latter states the requirement. After this conversation and looking over the builtin error messages I'm thinking the former is the way to go as a rough principle.

QuarkJets posted:

If this software is going to be used in big experiments, then it'd probably be best to even pre-check the inputs for validity and just immediately raise an exception that points to a piece of input and very briefly describes the issue.

That's the idea, it's sort of a pre-check as the ordering is all being done as the experiment is created which is before any sessions are run.

Dren posted:

It seems like you're trying really hard to generate meaningful error messages that provide a lot of help for the user. You should have clear error messages but save the more serious explanations for the documentation.

Yes, this is the other lesson I'm learning. Thanks.

Dominoes
Sep 20, 2007

Does anyone know how to expand a Pandas DatetimeIndex/timeseries? I've had success using Pandas from a created dictionary, but am having trouble modifying/expanding the data.

Starting from scratch, I'm trying this:

Python code:
def create_blank_data():
    dates = pd.date_range(start=dt.date(2008, 1, 1), end=dt.date.today())
    attrs = ['Open', 'High', 'Low', 'Close', 'Volume', 'Adj Close']
    symbols_ = symbols.read()
    data = np.zeros((len(symbols_), len(dates), len(attrs)))
    return pd.Panel(data, items=symbols_, major_axis=dates, minor_axis=attrs)
(Note that setting the blank data to 0s causes a problem I'll encounter later; if anyone can solve this, I'm curious as well: There can be three types of ways the panel will respond to a data that doesn't exist: 0, for panel placeholder info, numpy.nan for missing data, ie stock data on weekends, and keyerrors for dates before/after what's defined in the panel.)

I can then populate the initial data like this:
Python code:
def test_fresh_data():
    data = create_blank_data()
    for symbol in symbols.read():
        data[symbol] = api(symbol, start='2010-01-01') # returns a Dataframe.
    return data
This seems to work, but, I'm unable to expand the data.

If any of the dataframes I load contain newer data, I'd like to update the panel. (For now, I'm postponing the issue of adding data from a new DF without replacing existing data instead of overwriting it. If you have thoughts on this, I'm curious as well.) If I update the panel using another "data[symbol] = api(symbol, start='2010-01-01')" line, data with a newer dates than is defined in the panel is ignored. My thought it to explicitly expand the panel's date range first.

'data.majoraxis.max = dt.datetime.now()' seems to set data.majoraxis.max, but leaves data.majoraxis the same, and doesn't solve anything.

'data.majoraxis = pd.date_range(start=data.major_axis.min(), end=dt.date.today())' results in a length mismatch

I've been using this page as reference.

edit: Found this.

quote:

Panels can not expand along the major and minor axis after they are created (at least in a painless manner).
Balls. Any good alternatives? Is Pandas the wrong tool for data that expands over time? I'm trying a list of dataframes, but now can't figure out how to save that as HDF5. Pandas methods no longer work, and the h5py module's docs are cryptic, even though groups are dict-like.

For example, this doesn't work:
Python code:
def saveall_nopd(data, filename):
    with h5py.File("hist_data.h5", 'w') as f:
        f['data'] = data # data is a dict of dataframes

Dominoes fucked around with this message at 16:30 on Jan 18, 2014

Megaman
May 8, 2004
I didn't read the thread BUT...
I'm trying to eliminate a global logic block in a script I have, I have the following:

if args.foo == 'bar':
biz == 'baz'
elif arg.foo == 'fi' or 'fu:
biz == 'buz'

some_string = ("blah %s blah") % (biz)

Is there a way I can cram the top into the variable injection of a string so as to eliminate the global?:

some_string = ("blah %s blah") % (if args.foo == 'bar':
biz == 'baz'
elif arg.foo == 'fi' or 'fu:
biz == 'buz')

Dren
Jan 5, 2001

Pillbug

Megaman posted:

I'm trying to eliminate a global logic block in a script I have, I have the following:

if args.foo == 'bar':
biz == 'baz'
elif arg.foo == 'fi' or 'fu:
biz == 'buz'

some_string = ("blah %s blah") % (biz)

Is there a way I can cram the top into the variable injection of a string so as to eliminate the global?:

some_string = ("blah %s blah") % (if args.foo == 'bar':
biz == 'baz'
elif arg.foo == 'fi' or 'fu:
biz == 'buz')

please use the code tags when posting code. e.g.:
Python code:
if args.foo == 'bar':
    biz == 'baz'
elif arg.foo == 'fi' or 'fu:
    biz == 'buz'

some_string = ("blah %s blah") % (if args.foo == 'bar':
                                  biz == 'baz'
                                  elif arg.foo == 'fi' or 'fu:
                                  biz == 'buz')
I assume you meant to assign with = instead of ==. The answer to your question is yes. Python supports inline if.

A simple example
code:
>>> 10 if True else 20
10
>>> 10 if False else 20
20
An example for your use-case
Python code:
>>> foo = 'bar'
>>> "blah %s blah" % 'baz' if foo == 'bar' else 'buz' if foo in ['fi', 'fu'] else ''
'blah baz blah'
>>> foo = 'fi'
>>> "blah %s blah" % 'baz' if foo == 'bar' else 'buz' if foo in ['fi', 'fu'] else ''
'buz'
>>> foo = 'fu'
>>> "blah %s blah" % 'baz' if foo == 'bar' else 'buz' if foo in ['fi', 'fu'] else ''
'buz'
>>> foo = 'poop'
>>> "blah %s blah" % 'baz' if foo == 'bar' else 'buz' if foo in ['fi', 'fu'] else ''
''

Lysidas
Jul 26, 2002

John Diefenbaker is a madman who thinks he's John Diefenbaker.
Pillbug

Megaman posted:

elif arg.foo == 'fi' or 'fu'

Dren didn't explicitly say it, but this does not do what you intended.

Megaman
May 8, 2004
I didn't read the thread BUT...

Lysidas posted:

Dren didn't explicitly say it, but this does not do what you intended.

Yup, I saw that only when I tewsted both methods. What he mentioned works, if foo in ['fi', 'fu']. I'm almost entirely globalless now, hooray!

Jose Cuervo
Aug 25, 2004
I was looking at the answer to this question on Stack Overflow and have a question regarding why/ how the solution works. In the lambda function, does x refer to an entire list/ array (i.e., does x refer to all the values in a given group)? If so, does the solution work because of broadcasting in numpy (which I believe is when you divide a numpy array by a scalar each individual element in the array is divided by the scalar)?

QuarkJets
Sep 8, 2008

x is an array, and yes, it works because numpy broadcasting. The every element in the array is converted to float and then every element in the entire array is divided by the array's sum

Dominoes
Sep 20, 2007

Dominoes posted:

Does anyone know how to expand a Pandas DatetimeIndex/timeseries? I've had success using Pandas from a created dictionary, but am having trouble modifying/expanding the data.
I found a temp workaround: using a dict of dataframes, and saving each dataframe. I haven't tackled the smartly-adding data, so each API update replaces the entire dataframe. This works, but loading the initial data is much slower than with a single panel.

OnceIWasAnOstrich
Jul 22, 2006

Dominoes posted:

I found a temp workaround: using a dict of dataframes, and saving each dataframe. I haven't tackled the smartly-adding data, so each API update replaces the entire dataframe. This works, but loading the initial data is much slower than with a single panel.

This is similar to what I usually end up doing instead of using Panels. They just don't ever do quite what I expect them to do.

Dominoes
Sep 20, 2007

I feel like allowing panels to expand in any dimension would be easy to implement. I'm guessing a workaround would be to transpose, add an item, then transpose back, since AFAIK you can add items. (dimension 0)

SurgicalOntologist
Jun 17, 2004

The same issue is there with DataFrames: you can easily add columns, but not rows (this might be your roadblock that forces you to recreate the DataFrame on each update). In my limited experience and browsing of StackOverflow the usual recommendation is to factor out your data acquisition and your data manipulation. In other words, build up your data in a dict, and only turn it into a DataFrame/Panel when you're manipulating it.

It works fine for me since data acquisition is entirely finished before data manipulation begins, though I could see this being a performance issue in a stock ticker application.

Pollyanna
Mar 5, 2005

Milk's on them.


I'm using Unsemantic to make a grid out of my registration form, but it looks kinda funky.



The labels don't line up vertically with the text fields. How do I align them?

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
That one is probably more suited to the Web Development megathread, may want to ask over there and provide some sample code.

I have a question about the Image.save() method in PIL/Pillow. I see examples of code using arguments like quality and optimize, but I can't find any details about what they do or how they work in the documentation. Where can I find out more details about them?

salisbury shake
Dec 27, 2011
I've never played with PIL/etc before, but open up the REPL (ipython is great) and
Python code:
help(Image.save)
You'll get a manpage-esque readout, and if they put in docstrings, you might get a nice English explanation of what the kwargs do.

Worse comes to worst, go dig up the source file that defines the Image.save() method.

Reads almost like those kwarg's aren't actually defined in Image.save() but are eaten by **kwargs, and they serve as argument/value pairs to be dynamically passed to the image compressor.

edit: and/but swap. wth brain.

salisbury shake fucked around with this message at 02:32 on Jan 21, 2014

My Rhythmic Crotch
Jan 13, 2011

Pollyanna posted:

I'm using Unsemantic to make a grid out of my registration form, but it looks kinda funky.



The labels don't line up vertically with the text fields. How do I align them?
Normally you do something like this

Can we take a look at your app to see how it's progressing? Last I remember you were trying to get... a better UI going, or something.

Edit: I have never heard of unsemantic, most people are using either Bootstrap or Foundation. Not that I am a huge front guy, mind you. And if unsemantic works for you, then hey, run with it.

My Rhythmic Crotch fucked around with this message at 02:48 on Jan 21, 2014

Pollyanna
Mar 5, 2005

Milk's on them.


Yeah, I'm not really front OR back end. I'm very undifferentiated right now, and I'm just kinda generically clueless.

Here's the repo for the app. Forgive the embarrassing commit messages, I don't know how to change them. Any advice on the app as a whole would be nice.

Also, I could have sworn I posted that in the Web Dev thread...

Pollyanna fucked around with this message at 03:20 on Jan 21, 2014

My Rhythmic Crotch
Jan 13, 2011

Holy poo poo those commit descriptions are awesome.

Your app blew up when I tried to view a stock (http://localhost:5000/stocks?symbol=AAPL)

code:
Name: RSI50, Length: 1025 is not JSON serializable
Bokeh calls a json serialization on a date, which doesn't work until you do something like this. Without digging into the Bokeh code, I would imagine they have something equivalent though. So I don't know what's going on.

Pollyanna
Mar 5, 2005

Milk's on them.


I don't either, cause it works fine on the live site. :confused:

I saw that message once before, though, and it turned out that my dependencies were all messed up. I had to flatten and redo my virtualenv and install the packages one by one to get it to work again. Maybe that's what's happening to you?

Dren
Jan 5, 2001

Pillbug

fletcher posted:

That one is probably more suited to the Web Development megathread, may want to ask over there and provide some sample code.

I have a question about the Image.save() method in PIL/Pillow. I see examples of code using arguments like quality and optimize, but I can't find any details about what they do or how they work in the documentation. Where can I find out more details about them?

What jpeg quality means varies from encoder to encoder, it is not actually part of the standard. That said, it is usually (as in I've never seen anything other than) an integer between 1-100. Experiment with the encoder you are using to find a value that works for you. I don't know what PIL is doing when the optimize flag is turned on. Perhaps you could find something in their docs.

My Rhythmic Crotch
Jan 13, 2011

Pollyanna posted:

I don't either, cause it works fine on the live site. :confused:

I saw that message once before, though, and it turned out that my dependencies were all messed up. I had to flatten and redo my virtualenv and install the packages one by one to get it to work again. Maybe that's what's happening to you?
Ah okay, it's probably a dependency issue since I just haphazardly ran the app.

It's looking pretty cool! I'd put each graph in its own tab panel, but other than that, great job I'd say!

SurgicalOntologist
Jun 17, 2004

It's me again, looking for advice on API design. This is for the interacting-with-hardware-sensors library, not the psychology-experiments library.

What I'm trying to figure out is some way to make the API more similar for two use cases: using a hardware tracker, and using a mouse in its place (e.g., for testing away from the lab). Everything's working, but I'd like to clean up the API.

Here's what it looks like now. This is a simple test script that places a circle at the location of the tracker, and makes it smaller the further away from the table (read: screen) you hold it. The mouse works by registering as a tracker at distance=0 when it's clicked and some distance > 0 when it's not clicked.

Python code:
import pyglet

from vrpn_helper import VrpnServer, PolhemusLibertyLatus
from table import Table, Logger, TABLE_SIZE 
# I'm aware that Logger doesn't really belong with Table, will refactor
from polygon import Circle


def main(mouse=False, table_size=TABLE_SIZE):
    table = Table(size=table_size)

    if mouse:
        tracker = table.link_mouse(distance_when_not_pressed=5)
        run(table, tracker)

    else:  # use tracker
        tracker = PolhemusLibertyLatus(1, 115200)
        server = VrpnServer(tracker)
        with server.start():
            table.calibrate(tracker)
            run(table, tracker)


def run(table, tracker):
    circle = Circle((0, 0), 10)
    table.attach_shape_to_tracker(circle, tracker)

    logger = Logger()
    table.add_callback(tracker, logger.callback(tracker))

    @table.tracker_update(tracker)
    def update_circle_size(data):
        circle.radius = 15 - data['distance']

    pyglet.app.run()
    logger.disable('all')

    print(logger.to_dataframe(tracker))
I'll leave out the argparse stuff, it just sets mouse and TABLE_SIZE.

First of all, after writing this out I'm realizing that being able to add callbacks through a method as well as a decorator might be overkill. The inconsistency is notable with both methods back-to-back, plus having to use nested functions might be overly complicated (I think the nested function is necessary with the decorator syntax because I first need the tracker and circle objects). Actually, even with just the table.add_callback syntax I think I'd need a nested function, or define a function that takes both the circle and the tracker, and add it as a callback with functools.partial. That also seems overly complicated. Anyone have a better idea? Or should I not worry about requiring nested functions?

Okay, the real reason I posted this is I'd like to be able to set up either the mouse or the tracker, then return from the if/else clause and keeping going. But since I'm using a contextmanager for the server (which runs the hardware devices) I can't leave the else clause. Here are some options:
  1. Make a dummy contextmanager for the mouse case, reference one or the other contextmanager in the if/else clause, but only call it in a with clause after returning from the if/else.
  2. Make a master 'convenience' contextmanager that handles the common use cases, setting up either the mouse or a tracker+server according to a flag. Perhaps it would also set up the table and return both the table and the tracker. Perhaps according to a flag it could also manage a logger..
  3. A better idea altogether. It seems like I'd be able to hide the server from the user completely for example (although 2 accomplishes this).

I guess the issue is which elements to start and top together. Elements are:
  • server (tracker case only)
  • table (read: screen). I can't think of any use case where the table doesn't start and stop with the server/trackers.
  • tracker(s) (each tracker handles one device, which could include multiple sensors. Multiple trackers should be supported, of course, but using one device at a time is far more common)
  • logger(s) (each logger can handle any amount of trackers, I can't think of a good reason to use multiple loggers except perhaps to group trackers so you could use enable/disable('all') instead of by tracker). The idea is that after each trial you would grab the data as a dataframe and then clear the old data or instantiate an empty logger.
  • Pyglet itself. It is started with pyglet.app.run() and exits with a keypress callback automatically set by table, the end of the script, or pyglet.app.exit(). In an experiment the interactive parts of the code will be bracketed by the manual calls.

Sorry I rambled on and on and probably provided way too much information. Any suggestions on a better way to tie all these elements together will be appreciated.

Pollyanna
Mar 5, 2005

Milk's on them.


I'm trying to flash some messages in Flask, and I keep running into a problem. I have this code:

Python code:

@app.route('/stocks')
def lookup():
    if request.method == 'GET':
        s = request.args.get('symbol')

        try:
            len(s)
        except TypeError:
            flash('Please request a stock symbol.')
            return redirect(url_for('lookup'))

        if len(s) == 0:
            flash('Please request a stock symbol.')
            return redirect(url_for('lookup'))

        symbols_list = s.split(',')

        snippet_dict = {}

        for i in symbols_list:
            try:
                snippet_dict[i] = plots.build_plot(i.upper())
            except IOError:
                continue

        if len(snippet_dict) == 0:
            flash('No valid symbols found.')
            return redirect(url_for('lookup'))

        return render_template('stocks.html',
                               snippet_dict=snippet_dict)
and this in my template:

Python code:
{% with messages = get_flashed_messages() %}
    {% if messages %}
        <div class="grid-70" id="messages">
            <ul class="flashes">
                {% for message in messages %}
                    <li>{{ message }}</li>
                {% endfor %}
            </ul>
        </div>
    {% endif %}
{% endwith %}
However, whenever I try to visit / or /stocks, Chrome freaks out and tells me I'm running into a redirect loop. Why? I thought I could use message flashing for errors?

Haystack
Jan 23, 2005





If you visit /stocks with a blank or malformed query string, your code is redirecting the client... back to /stocks with a blank query string. Infinite loop.

Adbot
ADBOT LOVES YOU

Pollyanna
Mar 5, 2005

Milk's on them.


So how do I handle when the page is first loaded? I'm expecting the user to load the page, attempt to search from the searchbar, and if the input is blank or none then it would put a message onscreen "please enter search terms" or something.

  • Locked thread